我不理解std :: result_of和decltype的这些用法

时间:2017-10-03 10:06:39

标签: c++ c++11 templates generics decltype

在我的Visual Studio项目中,我有以下内容并且工作正常:

template <typename T>
void function(T type)
{

    std::result_of<T()>::type myVar = 5; // This compiled fine with Visual Studio, 
but with GCC it shows the following errors:
    //error: dependent-name ‘std::result_of<T()>::type’ is parsed as a non-type, 
    //but instantiation yields a type. note: say ‘typename std::result_of<T()>::type’ if a type is meant
}

int main() {

    auto lambda = []() { return float(); };
    function(lambda);
    return 0;
}

我只是想明白,编译器是否坚持我在std :: result_of前加上&#34; typename&#34;因为它可能是不明确的,因为std :: result_of可以返回一个类,然后:: type可以是该类的成员?这就是为什么它坚持要添加typename?如果是这种情况,为什么Visual Studio允许它?它不合规吗?

另外,因为我已经读过从C ++ 14或C ++ 17开始不推荐使用result_of,我想尝试使用更通用的decltype,它应该适用于更多情况。所以我试过了:

template <typename T>
void function(T type)
{
decltype(T()) myVar = 5; // Error, use of deleted function‘main()::<lambda()>::<lambda>()’  main.cpp    
}

所以我知道lambda有一个删除的默认构造函数和复制赋值运算符,但是在这种情况下我真的认为在将lambda传递给这个模板化函数时会调用lambda的复制构造函数,它有它。然后当我做decltype(T())时我假设这将调用它的operator()函数。我不明白为什么它会说删除功能。

最后我尝试了:

decltype(std::declval<T()>) myVar = 5;

因为我认为declval可以用来创建你所做的任何电话的假实例,至少它是如何向我解释的。这也失败了,错误:

  

&#34;“main()::&amp;&amp;”类型的引用无效初始化   来自'int&#34;

类型的表达式

1 个答案:

答案 0 :(得分:4)

<强>的result_of

首先,GCC编译器在typename之前需要关键字std::result_of,因为后者的返回值是一个类。而且你必须指示它使用它的类型来声明一个新变量。

关于你的评论:

  

另外,因为我已经读过从C ++ 14或C ++ 17开始不推荐使用result_of

std::result_of自C ++ 17(See here why)起不推荐使用,并被替换为 新引入的std::invoke_result,如果你有一个兼容的编译器,你可以使用它。

<强> decltype

由于std::result_ofdecltype方式按以下方式声明:

  template<typename _Signature>
  struct result_of;

  template<typename _Functor, typename... _ArgTypes>
  struct result_of<F(Args...)> {
      typedef decltype( std::declval<F>()(std::declval<Args>()...) ) type;
  };

您可以使用类似的定义:

decltype( std::declval<T>()() ) myVar = 5;