C++ 传递到std::result_之前的衰减类型

C++ 传递到std::result_之前的衰减类型,c++,templates,c++11,c++14,C++,Templates,C++11,C++14,如本页所示,C++14中的std::async的签名之一已从C++11版本更改 template< class Function, class... Args> std::future<typename std::result_of<Function(Args...)>::type> async( Function&& f, Args&&... args ); 将打印出四个trues.更改响应。问题是async(如bi

如本页所示,C++14中的
std::async
的签名之一已从C++11版本更改

template< class Function, class... Args>
std::future<typename std::result_of<Function(Args...)>::type>
    async( Function&& f, Args&&... args );

将打印出四个
true
s.

更改响应。问题是
async
(如
bind
等)decay复制了它的所有参数,因此如果在返回类型中没有使用
decay
,那么在涉及ref限定和/或rvalue时,您将得到错误的返回类型:

struct F {
    int operator()() &;
    char operator()() &&;

    int operator(int& ) const;
    char operator(int&& ) const;
};

auto future = std::async(F{}); // actually gives future<int>, but says
                               // it gives future<char>?
auto future2 = std::async(F{}, 1); // ditto
struct F{
int运算符()()&;
char运算符()()&;
int运算符(int&)const;
字符运算符(int&&)常量;
};
auto future=std::async(F{});//实际上给未来,但是说
//它给了未来?
autofuture2=std::async(F{},1);//同上
由于async的所有参数都被构造到其内部对象中,因此需要巧妙地包装它们,以便实际实现参数的右值


这是有意义的-
async
必须将其参数存储在某个位置,如果传入右值,则它必须拥有这些参数的所有权。如果它持有右值引用,底层对象可能会被破坏。但是,一旦它将其存储为
T
,它就不知道它来自
T&
T&
——在这一点上它只有一个命名的左值参数

我认为它对引用函数类型有意义。@101010没有
decay
删除引用限定?@101010请查看我的更新。啊。这就是为什么我们真正喜欢C++的原因。请注意,新版本意味着它<代码>移动< /代码> s,将其内部存储的函数和参数转换为调用表达式,这也是正确的事情。@ yAK不同于“代码> bDand())/>代码>的语义使它非常混乱。我意识到线程/异步是一个调用,而bind可能是多个调用,但它仍然是。。。混淆。这就是为什么
bind
需要一个右值重载的
操作符()
和一个左值重载的
操作符()
来处理这个问题。与lambdas类似:在右值上下文中,他们可能应该在最后一次使用时将其本地状态视为右值。另一方面,不确定如何使语法安全、不出人意料且高效,因此。。。(这并不奇怪!)@ZizhengTai,因为他们是以右值的形式搬进来的。如果您不
decay\u t
,您将检查返回类型,就像它们可能是左值一样。
#include <iostream>
#include <type_traits>

int main()
{
    auto fn = [](auto x) -> int { return x + 1; };

    using Fn = decltype(fn);
    using FnRef = Fn&;
    using FnCRef = const Fn&;
    using FnRRef = Fn&&;

    std::cout << std::boolalpha
              << std::is_same<int, std::result_of_t<Fn(int)>>::value << '\n'
              << std::is_same<int, std::result_of_t<FnRef(int)>>::value << '\n'
              << std::is_same<int, std::result_of_t<FnCRef(int)>>::value << '\n'
              << std::is_same<int, std::result_of_t<FnRRef(int)>>::value << '\n';

    return 0;
}
struct F {
    int operator()() &;
    char operator()() &&;

    int operator(int& ) const;
    char operator(int&& ) const;
};

auto future = std::async(F{}); // actually gives future<int>, but says
                               // it gives future<char>?
auto future2 = std::async(F{}, 1); // ditto