C++ 支持`自动&&;`对于MSVC++;2017

C++ 支持`自动&&;`对于MSVC++;2017,c++,c++14,visual-studio-2017,c++17,auto,C++,C++14,Visual Studio 2017,C++17,Auto,因此,他们建议使用以下代码: #include <iostream> template <typename F> class Finally { F f; public: template <typename Func> Finally(Func&& func) : f(std::forward<Func>(func)) {} ~Finally() { f(); } Finally(con

因此,他们建议使用以下代码:

#include <iostream>

template <typename F>
class Finally {
    F f;
public:
    template <typename Func>
    Finally(Func&& func) : f(std::forward<Func>(func)) {}
    ~Finally() { f(); }

    Finally(const Finally&) = delete;
    Finally(Finally&&) = delete;
    Finally& operator =(const Finally&) = delete;
    Finally& operator =(Finally&&) = delete;
};

template <typename F>
Finally<F> make_finally(F&& f)
{
    return Finally<F>{ std::forward<F>(f) }; // This doesn't compile
    //This compiles: return { std::forward<F>(f) };
}


int main()
{
    auto&& doFinally = make_finally([&] { std::cout<<", world!\n"; });
    std::cout << "Hello";
}
#包括
模板
终于上课了{
F;
公众:
模板
最后(Func&&Func):f(std::forward(Func)){
~Finally(){f();}
Finally(const Finally&)=删除;
Finally(Finally&&)=删除;
Finally&运算符=(const Finally&)=删除;
Finally&运算符=(Finally&&)=删除;
};
模板
Finally make_Finally(F&&F)
{
最后返回{std::forward(f)};//这不会编译
//编译:返回{std::forward(f)};
}
int main()
{
auto&&doFinally=make_finally([&]{std::cout)
那么
return{std::forward(f)};
return Finally{std::forward(f)};

前者在适当位置初始化返回对象。因此,当您:

X foo() { return {a, b, c}; }
auto&& res = foo();

这将在适当的位置构造一个
X
,然后将
res
绑定到它。任何地方都没有移动。没有一个移动会因为RVO而被省略,也没有一个移动会因为C++17中有新的值类别而被省略。在任何时候,我们甚至都没有考虑移动任何东西。只有一个移动
X
(即使在C++11中,即使使用
-fno-elide构造函数,因为没有对elide的构造函数调用)

相比之下,这:

X bar() { return X{a, b, c}; }
auto&& res2 = bar();
在C++17之前,将创建一个临时的
X
,然后将其移动到
bar()的返回中
。这将是RVO的候选项,移动肯定会被删除,但为了删除移动,移动实际上必须可以从一开始。在我们的例子中,
X
的移动构造函数被删除,因此此代码格式不正确。这导致了一种情况,Richard Smith在中的评论最能描述这种情况:

在C++17之后,没有临时值。我们有一个类型为
X
的prvalue,用于初始化
bar()
的返回对象,因此我们只需从prvalue的初始值设定项初始化返回对象。该行为相当于上面的
foo()
示例。不会进行任何移动

那么
return{std::forward(f)};
return Finally{std::forward(f)};

前者在适当位置初始化返回对象。因此,当您:

X foo() { return {a, b, c}; }
auto&& res = foo();

这将在适当的位置构造一个
X
,然后将
res
绑定到它。任何地方都没有移动。没有一个移动会因为RVO而被省略,也没有一个移动会因为C++17中有新的值类别而被省略。在任何时候,我们甚至都没有考虑移动任何东西。只有一个移动
X
(即使在C++11中,即使使用
-fno-elide构造函数,因为没有对elide的构造函数调用)

相比之下,这:

X bar() { return X{a, b, c}; }
auto&& res2 = bar();
在C++17之前,将创建一个临时的
X
,然后将其移动到
bar()的返回中
。这将是RVO的候选项,移动肯定会被删除,但为了删除移动,移动实际上必须可以从一开始。在我们的例子中,
X
的移动构造函数被删除,因此此代码格式不正确。这导致了一种情况,Richard Smith在中的评论最能描述这种情况:


在C++17之后,没有临时值。我们有一个类型为
X
的prvalue,用于初始化
bar()
的返回对象,因此我们只需从prvalue的初始值设定项初始化返回对象。其行为相当于
foo()
上面的示例。不会执行任何移动。

自动和
应该由MSVC支持。
Finally make\u Finally(F&&F)
不应该是
Finally make\u Finally(F&&F)
?为什么要用Clang编译?来自
make\u Finally
的返回要调用(已删除)移动
Finally
的构造函数。如果它被优化了,它应该仍然需要可用。@1201程序如果
make\u Finally
是RVO的候选对象,因为C++17保证了RVO,你不需要移动构造函数iircpeens!这里没有移动。
make\u Finally()
直接在返回对象中创建一个
Finally
,然后将其绑定到引用
doFinally
。即使没有新的值类别,也不会在任何地方移动,即使使用
-fno elide构造函数
MSVC应支持
自动和
Finally make\u Finally(F&&F)
这不应该是
Finally make\u Finally(F&&F)
?为什么要用叮当声编译?来自
make\u Finally
的返回要调用(已删除)移动
Finally
的构造函数。如果它被优化了,它应该仍然需要可用。@1201程序如果
make\u Finally
是RVO的候选对象,因为C++17保证了RVO,你不需要移动构造函数iircpeens!这里没有移动。
make\u Finally()
直接在返回对象中创建一个
Finally
,然后将其绑定到引用
doFinally
。任何地方都不会移动,即使没有新的值类别,即使使用
-fno elide构造函数也不会。我不会说“直接初始化”,太容易混淆。@T.C.在所有地方都删除了“直接”这个词。很难仔细挑选在不同上下文中没有不同含义的词。“任何地方都没有移动。没有一个移动会因为RVO而被省略,也没有一个移动会因为C++17中新的值类别而被省略。”。这是非常令人困惑的,因为您将“完全不移动”和“在C++17中保证忽略的移动”区分开来。因此1@JohannesSchaub-我想litb不能让每个人都满意。我试图确定没有移动的原因不是因为C++17。调用实际的论文也无济于事“保证拷贝省略”我不会说“direc”