奇怪的result_of< F(Ts ...)>在Andrei Alexandrescu的谈论爆炸元组 [英] the weird result_of<F(Ts...)> in Andrei Alexandrescu's talk about exploding tuple
问题描述
有人看过Andrei Alexandrescu在GoingNative2013中关于爆炸元组的演讲吗?
这里是我不太喜欢的代码:
模板< class F,class ... Ts>
auto explode(F&& f,const tuple< Ts ...>& t)
- > typename result_of< F(Ts ...)> :: type
{
return Expander< sizeof ...(Ts),
typename result_of< F ; :: type,
F,
const tuple< Ts ...>&> :: expand(f,t);
}
F(Ts ...)我的意思是:F不是一个函数类型?
我知道R(Ts ...)很好,但R这里是一个返回类型,但使用F在R应该的地方,这是驱使我疯了...
任何人都可以帮助我理解这奇怪的F(Ts ...)吗?
这里是链接到Andrei Alexandrescu的话:
http://channel9.msdn。 com / Events / GoingNative / 2013 / The-Way-of-the-Exploding-Tuple
你想问的可能是这个的一个重复:为什么std :: result_of将一个(不相关的)函数类型作为类型参数?
让我们剖析:
std :: result_of< F(Ts ...)> :: type
pre>
因此,在
命名空间std
中的某处,我们有一个类模板result_of< ;>
。它需要一个模板类型参数;即它看起来基本上是这样的:template< typename Foo>
struct result_of
{
typedef FOOBARBAZ type;
};
好的,我们使用参数
F Ts ...)
。这是不寻常的语法!您可能知道Ts
是一个参数包,因此括号内的Ts ...
将在编译时展开时间到以逗号分隔的类型列表,例如int,double,bool
。所以我们有F(int,double,bool)
。
就像
int(char)
表示函数取char
并返回int
,F(int,double,bool)
意味着int,double,bool
并返回F
的函数。
但等等,你说。 我认为
F
已经是我的功能类型了!
是的。
F
是 您的 功能类型。但是std :: result_of
所期望的类型是真的!该函数类型包装在另一个 。详细说明:typedef int(* F)(char);
typedef F G(char);
static_assert(std :: is_same< std :: result_of< G> :: type,int> :: value);
static_assert(std :: is_same< std :: result_of< F(char)> :: type,int> :: value);
static_assert(std :: is_same< std :: result_of< int(*(char))(char)> :: type,int> :: value);
上面的每一行都是等价的:
F code>只是一种更美观的方式来写
int(*(char))(char)
。当然,你不能总是得到它,因为有时F
是不能从函数返回的函数类型:typedef int F(char);
std :: result_of< F(char)> ;; //未能编译
正如@Simple在评论中写道,
std: :result_of< F(Ts ...)> :: type
总是可以用较不聪明的表达式来替换,但是也不太混淆。decltype(std :: declval< F>()(std :: declval< Ts>()...))
即,调用
F 值的结果的
decltype
code>的类型为Ts ...
的参数。这里没有古怪的更高级别的函数类型;一切都是你自然希望的个人来说,我可能在我自己的代码中使用decltype
方法,只是因为它更容易理解;但我想象一些人喜欢std :: result_of
方法,因为它看起来表面上更简单,并且被标准祝福。对每个他自己。:)Has anyone watched Andrei Alexandrescu's talk about exploding tuple in GoingNative2013 yet?
Here is the piece of code I don't quite follow:
template <class F, class... Ts> auto explode(F&& f, const tuple<Ts...>& t) -> typename result_of<F(Ts...)>::type { return Expander<sizeof...(Ts), typename result_of<F(Ts...)>::type, F, const tuple<Ts...>&>::expand(f, t); }
the F(Ts...) in result_of trouble me much. I mean: doesn't F stands for a function type ? I know R(Ts...) well, but the R here is a return type, but using F in place where R should be, that's the thing driving me crazy...
Can anyone help me understand the weird F(Ts...) here ?
Here is the link forward to Andrei Alexandrescu's talk: http://channel9.msdn.com/Events/GoingNative/2013/The-Way-of-the-Exploding-Tuple
解决方案The question you want to ask is probably a duplicate of this one: Why does std::result_of take an (unrelated) function type as a type argument?
Let's dissect:
std::result_of<F(Ts...)>::type
So, somewhere in
namespace std
, we've got a class templateresult_of<>
. It takes one template type parameter; i.e., it looks basically like this:template<typename Foo> struct result_of { typedef FOOBARBAZ type; };
Okay, so, we're instantiating this template with the parameter
F(Ts...)
. That's unusual syntax! You presumably know thatTs
is a parameter pack, and therefore theTs...
inside the parentheses will expand at compile time to a comma-separated list of types, for exampleint, double, bool
. So we've gotF(int, double, bool)
. Okay, that's a function type.Just as
int(char)
means "function takingchar
and returningint
", so doesF(int, double, bool)
mean "function takingint, double, bool
and returningF
"."But wait," you say. "I thought
F
was already my function type!"Yes.
F
is your function type. But the type expected bystd::result_of
is, really!, that function type wrapped up in another function type. To elaborate:typedef int (*F)(char); typedef F G(char); static_assert(std::is_same< std::result_of<G>::type, int >::value); static_assert(std::is_same< std::result_of<F(char)>::type, int >::value); static_assert(std::is_same< std::result_of<int (*(char))(char)>::type, int >::value);
Each of the above lines is exactly equivalent:
F(char)
is just a much more aesthetically pleasing way of writingint (*(char))(char)
. Of course, you can't always get away with it, because sometimesF
is a function type that can't be returned from a function:typedef int F(char); std::result_of<F(char)>; // fails to compile
As @Simple wrote in the comments,
std::result_of<F(Ts...)>::type
can always be replaced with the less clever but also less confusing expressiondecltype( std::declval<F>() ( std::declval<Ts>()... ) )
i.e., "the
decltype
of the result of calling a value of typeF
with arguments of typesTs...
. Here, there are no wacky higher-level function types; everything just works the way you'd naturally expect it to. Personally, I would probably use thedecltype
approach in my own code, just because it's easier to understand; but I imagine that some people would prefer thestd::result_of
approach because it looks superficially simpler and is blessed by the Standard. To each his own. :)这篇关于奇怪的result_of< F(Ts ...)>在Andrei Alexandrescu的谈论爆炸元组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!