简体   繁体   English

std :: result_of简单函数

[英]std::result_of simple function

#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;
}

Please explain why std::result_of<f(int)>::type x; 请解释为什么std::result_of<f(int)>::type x; is invalid... 是无效的...

cppreference says "( std::result_of ) Deduces the return type of a function call expression at compile type.". cppreference说“( std::result_of )在编译类型中减去函数调用表达式的返回类型。”

what's the problem? 有什么问题?

std::result_of<T> requires T to be a type --but not just any type. std::result_of<T>要求T是一个类型 - 但不仅仅是任何类型。 T must be a function type so this partial specialization of result_of will be used: T必须是函数类型,因此将使用result_of部分特化:

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

such that: 这样:

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

is well-formed (C++11 20.9.7.6). 形式良好(C ++ 11 20.9.7.6)。 (INVOKE is defined in 20.8.2.) (INVOKE在20.8.2中定义。)

The reason std::result_of<f(int)> does not work is because f is not a type --it is an instance of a function type. std::result_of<f(int)>不起作用的原因是因为f不是类型--it是函数类型的实例。 To declare x to be the return type of f applied to an int , simply write this: 要声明x是应用于intf的返回类型,只需写下:

decltype(f(int{})) x;

or if you prefer hard-coding an int : 或者如果您更喜欢对int硬编码:

decltype(f(32)) x;

If the type of f is desired then use: 如果需要f的类型,那么使用:

using FuncPtr = decltype(f);

In the provided code F (ie, not lower case f ) however is a type and so F(int) defines a the type representing the function that returns F accepting an int as an argument. 在提供的代码F (即,不是小写的f )中,然而是一个类型,因此F(int)定义了一个表示函数的类型,该函数返回F接受int作为参数。 Clearly this is not what F is! 显然,这不是F! F 's type is a struct whose instances can use the function call operator. F的类型是一个结构,其实例可以使用函数调用运算符。 F also has no explicit or implicit constructors taking an int , etc. as well. F也没有显式或隐式构造函数来获取int等。 How can this work? 这怎么办? Short answer: Template "magic". 简答:模板“魔术”。

Essentially, the definition of std::result_of takes the type, F(int) and separates the return type from the argument types so it can determine which case of INVOKE() would allow it to work. 本质上, std::result_of的定义采用类型F(int)并将返回类型与参数类型分开,以便它可以确定INVOKE()的哪种情况允许它工作。 The cases of INVOKE are: INVOKE的案例是:

  1. F is a pointer to a member function for some class T F是指向某个类T的成员函数的指针
  2. If there is only one argument, F is a pointer to a data member of class T, or, 如果只有一个参数,则F是指向T类数据成员的指针,或者,
  3. An instance of F can be used as a function, ie, F的实例可以用作函数,即
declval<F>()(declval<int>())

which can be a normal function call or some type of functor (eg, like your example). 这可以是正常的函数调用或某种类型的函子(例如,像你的例子)。

Once this has been determined result_of can then determine the return type of the valid expression. 一旦确定了结果, result_of就可以确定有效表达式的返回类型。 This is what is returned via result_of 's type member. 这是通过result_oftype成员返回的内容。

The beautiful thing about this is that the user of result_of need not know anything about how this actually works. 关于这一点的美妙之处在于result_of的用户不需要知道它实际上是如何工作的。 The only thing one has to understand is that result_of needs a function TYPE. 唯一需要理解的是result_of需要一个函数TYPE。 If one is using names that are not types within code (eg, f ) then decltype will need to be used to obtain the type of an expression with such. 如果使用的代码不是代码中的类型(例如, f ),则需要使用decltype来获取具有此类型的表达式的类型。

Finally, part of the reason why f cannot be considered as a type is because template parameters also allow constant values and f is a constant function pointer value. 最后, f不能被视为类型的部分原因是因为模板参数也允许常量值而f是常量函数指针值。 This is easily demonstrated (using the question's definition of f ): 这很容易证明(使用问题的f定义):

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

and later: 然后:

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

So to obtain the return value type of an expression properly invoking f with some int one would write: 因此,要获得正确调用表达式的返回值的类型f一些int要这样写:

decltype(f(int{}))

(Note: f is never called: the compiler simply uses the expression within decltype to determine its result ie, its return value in this instance.) (注意: f永远不会被调用:编译器只是使用decltype的表达式来确定它的结果,即它在这个实例中的返回值。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM