奇怪的result_of< F(Ts ...)>在Andrei Alexandrescu的谈论爆炸元组 [英] the weird result_of<F(Ts...)> in Andrei Alexandrescu's talk about exploding tuple

查看:116
本文介绍了奇怪的result_of< F(Ts ...)>在Andrei Alexandrescu的谈论爆炸元组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人看过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 template result_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 that Ts is a parameter pack, and therefore the Ts... inside the parentheses will expand at compile time to a comma-separated list of types, for example int, double, bool. So we've got F(int, double, bool). Okay, that's a function type.

Just as int(char) means "function taking char and returning int", so does F(int, double, bool) mean "function taking int, double, bool and returning F".

"But wait," you say. "I thought F was already my function type!"

Yes. F is your function type. But the type expected by std::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 writing int (*(char))(char). Of course, you can't always get away with it, because sometimes F 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 expression

decltype( std::declval<F>() ( std::declval<Ts>()... ) )

i.e., "the decltype of the result of calling a value of type F with arguments of types Ts.... 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 the decltype approach in my own code, just because it's easier to understand; but I imagine that some people would prefer the std::result_of approach because it looks superficially simpler and is blessed by the Standard. To each his own. :)

这篇关于奇怪的result_of&lt; F(Ts ...)&gt;在Andrei Alexandrescu的谈论爆炸元组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆