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

时间:2021-12-23 18:51:20

On my Visual Studio project I had the following and it worked fine:

在我的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;
}

I just want to understand, is the compiler insisting that I preface the std::result_of with "typename" because it could be ambiguous, in that std::result_of could return a class, and then ::type could be a member of that class? Is that why it's insisting that typename be added? If this is the case then why does Visual Studio allow it? Is it non compliant?

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

Also, because I've read that result_of is being deprecated as of C++14 or C++17, I wanted to try and use the more generic decltype, which is supposed to work in more circumstances. So I tried:

另外,因为我已经读过从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    
}

So I'm aware that a lambda has a deleted default constructor and copy assignment operator, but in this case I really think that when passing the lambda to this templated function the lambda's copy constructor is called, which it does have. Then when I do decltype(T()) I assume this would be calling its operator() function. I don't understand why it says something about deleted function.

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

And finally I tried with:

最后我尝试了:

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

Because I thought that declval can be used as if creating a fake instance of whatever call you make, at least that's how it was explained to me. This also fails with error:

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

"invalid initialization of reference of type ‘main()::&&’ from expression of type ‘int"

“从类型'int”的表达式初始化'main():: &&'类型的引用无效

1 个解决方案

#1


4  

result_of

First, the GCC compiler requires the keyword typename before std::result_of because the return value of the latter is a class. And you have to instruct it to use its type to declare a new variable.

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

Regarding your comment:

关于你的评论:

Also, because I've read that result_of is being deprecated as of C++14 or C++17

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

std::result_of is deprecated as of C++17 (See here why) and is replaced by the newly introduced std::invoke_result, so you could use it instead if you have a compliant compiler.

从C ++ 17开始,不推荐使用std :: result_of(请参见此处原因)并由新引入的std :: invoke_result替换,因此如果您有兼容的编译器,则可以使用它。

decltype

Since std::result_of is declared in terms of decltype in the following manner:

由于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;
  };

You could use a similar definition:

您可以使用类似的定义:

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

#1


4  

result_of

First, the GCC compiler requires the keyword typename before std::result_of because the return value of the latter is a class. And you have to instruct it to use its type to declare a new variable.

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

Regarding your comment:

关于你的评论:

Also, because I've read that result_of is being deprecated as of C++14 or C++17

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

std::result_of is deprecated as of C++17 (See here why) and is replaced by the newly introduced std::invoke_result, so you could use it instead if you have a compliant compiler.

从C ++ 17开始,不推荐使用std :: result_of(请参见此处原因)并由新引入的std :: invoke_result替换,因此如果您有兼容的编译器,则可以使用它。

decltype

Since std::result_of is declared in terms of decltype in the following manner:

由于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;
  };

You could use a similar definition:

您可以使用类似的定义:

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