[英]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
是应用于int
的f
的返回类型,只需写下:
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的案例是:
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_of
的type
成员返回的内容。
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.