gpt4 book ai didi

c++ - std::result_of 简单函数

转载 作者:IT老高 更新时间:2023-10-28 21:56:41 26 4
gpt4 key购买 nike

#include <iostream>
#include <type_traits>

double f(int i)
{
return i+0.1;
}

struct F
{
public:
double operator ()(int i) { return i+0.1; }
};

int
main(int, char**)
{
std::result_of<F(int)>::type x; // ok
// std::result_of<f(int)>::type x; // error: template argument 1 is invalid
x = 0.1;
std::cerr << x << std::endl;
}

请解释原因std::result_of<f(int)>::type x;无效...

cppreference 说“(std::result_of) 在编译类型推导出函数调用表达式的返回类型。”。

有什么问题?

最佳答案

std::result_of<T>需要 T成为一种类型——但不仅仅是任何类型。 T必须是函数类型,所以 result_of 的部分特化将被使用:

template <class Fn, class... ArgTypes> struct result_of<Fn(ArgTypes...)>;

这样:

decltype(INVOKE(declval<Fn>(), declval<ArgTypes>()...))

格式正确 (C++11 20.9.7.6)。 (INVOKE 在 20.8.2 中定义。)

原因std::result_of<f(int)>不工作是因为f不是类型——它是函数类型的实例。申报x成为 f 的返回类型应用于 int ,只需这样写:

decltype(f(int{})) x;

或者如果您更喜欢硬编码 int :

decltype(f(32)) x;

如果 f 的类型需要然后使用:

using FuncPtr = decltype(f);

在提供的代码中 F (即,不是小写 f )但是是一种类型,所以 F(int)定义表示返回 F 的函数的类型接受 int作为论据。显然这不是F! F的类型是一个结构体,其实例可以使用函数调用运算符。 F也没有采用 int 的显式或隐式构造函数等。这怎么行?简短回答:模板“魔法”。

本质上,std::result_of 的定义取类型,F(int)并将返回类型与参数类型分开,以便它可以确定 INVOKE() 的哪种情况允许它工作。 INVOKE的案例有:

  1. F 是指向某个类 T 的成员函数的指针
  2. 如果只有一个参数,则 F 是指向类 T 的数据成员的指针,或者,
  3. 可以将 F 的实例用作函数,即,
declval<F>()(declval<int>())

可以是普通的函数调用或某种类型的仿函数(例如,像您的示例)。

一旦确定result_of然后可以确定有效表达式的返回类型。这是通过 result_of 返回的内容的type成员(member)。

关于这个的美妙之处在于 result_of 的用户不需要知道这实际上是如何工作的。唯一需要了解的是result_of需要一个函数类型。如果使用的名称不是代码中的类型(例如 f ),则 decltype将需要使用此类来获取表达式的类型。

最后,f 的部分原因不能被视为类型是因为模板参数也允许常量值和 f是一个常量函数指针值。这很容易证明(使用问题对 f 的定义):

template <double Op(int)>
double invoke_op(int i)
{
return Op(i);
}

及以后:

std::cout << invoke_op<f>(10) << std::endl;

所以要正确调用 f 来获取表达式的返回值类型有一些 int有人会写:

decltype(f(int{}))

(注意:f 永远不会被调用:编译器只是使用 decltype 中的表达式来确定其结果,即在此实例中的返回值。)

关于c++ - std::result_of 简单函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11470802/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com