std::result_of简单的功能


#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(。(调用在 20.8.2 中定义。

std::result_of<f(int)>不起作用的原因是f不是类型 - 它是函数类型的实例。要将x声明为应用于intf的返回类型,只需编写以下内容:

decltype(f(int{})) x;

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

decltype(f(32)) x;

如果需要f类型,请使用:

using FuncPtr = decltype(f);

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

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

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

它可以是普通的函数调用或某种类型的函子(例如,像您的示例一样(。

确定后result_of就可以确定有效表达式的返回类型。这是通过result_oftype成员返回的内容。

这样做的美妙之处在于,result_of的用户不需要知道它实际上是如何工作的。唯一需要了解的是result_of需要一个函数 TYPE。如果使用的名称不是代码中的类型(例如,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;

因此,要获得使用某些int正确调用f表达式的返回值类型,可以编写:

decltype(f(int{}))

(注意:从不调用f:编译器只是使用decltype中的表达式来确定其结果,即在这种情况下的返回值。

相关内容

  • 没有找到相关文章

最新更新