std :: result_of简单函数

use*_*506 19 c++ std result-of c++11

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

请解释为什么std::result_of<f(int)>::type x;无效......

cppreference说"(std::result_of)在编译类型中扣除函数调用表达式的返回类型."

有什么问题?

Pau*_*ney 25

std::result_of<T>需要T是一种类型 - 但不仅仅是任何类型.T必须是函数类型,因此result_of将使用此部分特化:

template <class Fn, class... ArgTypes> struct result_of<Fn(ArgTypes...)>;
Run Code Online (Sandbox Code Playgroud)

这样:

decltype(INVOKE(declval<Fn>(), declval<ArgTypes>()...))
Run Code Online (Sandbox Code Playgroud)

形式良好(C++ 11 20.9.7.6).(INVOKE在20.8.2中定义.)

原因std::result_of<f(int)>不起作用是因为f它不是一个类型 - 它是一个函数类型的实例.要声明xf应用于a 的返回类型int,只需写下:

decltype(f(int{})) x;
Run Code Online (Sandbox Code Playgroud)

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

decltype(f(32)) x;
Run Code Online (Sandbox Code Playgroud)

如果f需要的话,请使用:

using FuncPtr = decltype(f);
Run Code Online (Sandbox Code Playgroud)

在提供的代码中F(即,不是小写f)但是是一个类型,因此F(int)定义了一个表示返回F接受a int作为参数的函数的类型.显然,这不是F!F的类型是一个结构,其实例可以使用函数调用运算符.F也没有明确或隐含的构造函数也使用int等等.这怎么办?简答:模板"魔术".

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

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

这可以是正常的函数调用或某种类型的函子(例如,像你的例子).

一旦result_of确定了这个,就可以确定有效表达式的返回类型.这是通过会员返回result_of的内容type.

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

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

template <double Op(int)>
double invoke_op(int i)
{
  return Op(i);
}
Run Code Online (Sandbox Code Playgroud)

然后:

std::cout << invoke_op<f>(10) << std::endl;
Run Code Online (Sandbox Code Playgroud)

因此,要获得正确调用表达式的返回值的类型f有一些int人会写:

decltype(f(int{}))
Run Code Online (Sandbox Code Playgroud)

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