我不了解std :: result_of和decltype的这些用法 [英] I'm not understanding these uses of std::result_of and decltype

查看:272
本文介绍了我不了解std :: result_of和decltype的这些用法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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具有类型名,因为它可能是含糊的,在该std :: result_of中可以返回一个类,然后:: type可以成为该类的成员吗?这就是为什么它坚持要添加类型名称吗?如果是这种情况,那么为什么Visual Studio允许它?还不合规吗?

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?

此外,由于我已经阅读到自C ++ 14或C ++ 17起不推荐使用result_of,因此我想尝试并使用更通用的decltype,应该在更多情况下使用。所以我尝试了:

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:

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()函数。我不明白为什么它会说一些有关删除功能的信息。

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.

最后我尝试了:

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

因为我认为declval可以像在调用时创建假实例一样使用至少那是对我的解释。这也会因错误而失败:

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:


类型为'main()::&&'
的引用的无效初始化从类型'int'

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


推荐答案

result_of

首先,GCC编译器在 std :: result_of typename $ c>,因为后者的返回值是一个类。并且必须指示它使用其类型来声明新变量。

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.

关于您的评论:


另外,因为我已经阅读到自C ++ 14或C ++ 17起不推荐使用result_of

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



从C ++ 17开始不推荐使用

std :: result_of 在这里查看原因),并用新引入的 std :: invoke_result 替换为
,所以您如果您有兼容的编译器,则可以改用它。

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.

decltype

std :: result_of 是按照 decltype 的以下方式声明的:

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

  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;

这篇关于我不了解std :: result_of和decltype的这些用法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆