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

Zeb*_*ish 2 c++ generics templates decltype c++11

在我的 Visual Studio 项目中,我有以下内容并且运行良好:

\n\n
template <typename T>\nvoid function(T type)\n{\n\n    std::result_of<T()>::type myVar = 5; // This compiled fine with Visual Studio, \nbut with GCC it shows the following errors:\n    //error: dependent-name \xe2\x80\x98std::result_of<T()>::type\xe2\x80\x99 is parsed as a non-type, \n    //but instantiation yields a type. note: say \xe2\x80\x98typename std::result_of<T()>::type\xe2\x80\x99 if a type is meant\n}\n\nint main() {\n\n    auto lambda = []() { return float(); };\n    function(lambda);\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我只是想了解,编译器是否坚持要求我在 std::result_of 前面加上“typename”,因为它可能不明确,因为 std::result_of 可以返回一个类,然后 ::type 可以是该类的成员班级?这就是为什么它坚持添加类型名吗?如果是这种情况,那么为什么 Visual Studio 允许这样做呢?是否不符合规定?

\n\n

另外,因为我读到 result_of 从 C++14 或 C++17 开始已被弃用,所以我想尝试使用更通用的 decltype,它应该在更多情况下工作。所以我尝试:

\n\n
template <typename T>\nvoid function(T type)\n{\ndecltype(T()) myVar = 5; // Error, use of deleted function\xe2\x80\x98main()::<lambda()>::<lambda>()\xe2\x80\x99  main.cpp    \n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

最后我尝试了:

\n\n
decltype(std::declval<T()>) myVar = 5;\n
Run Code Online (Sandbox Code Playgroud)\n\n

因为我认为 declval 可以像为您所做的任何调用创建一个假实例一样使用,至少这是向我解释的。这也会失败并出现错误:

\n\n
\n

“从 \xe2\x80\x98int 类型的表达式对 \xe2\x80\x98main()::&&\xe2\x80\x99\n 类型的引用进行无效初始化”

\n
\n

Dan*_*man 5

的结果

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

关于您的评论:

另外,因为我读到 result_of 从 C++14 或 C++17 开始已被弃用

std::result_of从 C++17 开始已弃用(请参阅此处原因),并被新引入的替代std::invoke_result,因此如果您有兼容的编译器,则可以使用它。

决定类型

由于按以下方式std::result_of声明:decltype

  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;
  };
Run Code Online (Sandbox Code Playgroud)

您可以使用类似的定义:

decltype( std::declval<T>()() ) myVar = 5;
Run Code Online (Sandbox Code Playgroud)