【问题标题】:std::result_of simple functionstd::result_of 简单函数
【发布时间】:2012-07-13 12:45:40
【问题描述】:
#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&lt;f(int)&gt;::type x;无效...

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

有什么问题?

【问题讨论】:

标签: c++ c++11 std result-of


【解决方案1】:

std::result_of&lt;T&gt; 要求 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&lt;f(int)&gt; 不起作用的原因是因为f 不是类型——它是函数类型的实例。要将x 声明为应用于intf 的返回类型,只需这样写:

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_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;

因此,要获得正确调用 f 和一些 int 的表达式的返回值类型,可以这样写:

decltype(f(int{}))

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

【讨论】:

    猜你喜欢
    • 2020-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-10
    • 1970-01-01
    • 1970-01-01
    • 2015-04-21
    • 1970-01-01
    相关资源
    最近更新 更多