Andrei Alexandrescu关于爆炸元组的讨论中<f(ts ...)>的奇怪结果</f(ts ...)>

时间:2013-09-13 04:57:25

标签: c++11 tuples

有没有人看过Andrei Alexandrescu在GoingNative2013中关于爆炸元组的讨论呢?

以下是我不太关注的代码:

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

结果中的F(Ts ...)让我很烦恼。我的意思是:F不代表功能类型吗? 我知道R(Ts ......)很好,但这里的R是一个返回类型,但是在R应该使用F的地方,这就是让我疯狂的事情......

有人能帮我理解奇怪的F(Ts ......)吗?

以下是Andrei Alexandrescu演讲的链接: http://channel9.msdn.com/Events/GoingNative/2013/The-Way-of-the-Exploding-Tuple

1 个答案:

答案 0 :(得分:1)

您想问的问题可能与此问题重复:Why does std::result_of take an (unrelated) function type as a type argument?

让我们剖析:

std::result_of<F(Ts...)>::type

所以,在namespace 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并返回{{1} }”。

“但等等,”你说。 “我以为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(char)。当然,你不能总是逃脱它,因为有时int (*(char))(char)是一个无法从函数返回的函数类型:

F

正如@Simple在评论中所写,typedef int F(char); std::result_of<F(char)>; // fails to compile 总是可以用不那么聪明但也不那么混乱的表达来代替

std::result_of<F(Ts...)>::type

即“使用decltype( std::declval<F>() ( std::declval<Ts>()... ) ) 类型的参数调用类型decltype的值的结果的F。这里,没有古怪的高级函数类型;一切都只是按照你自然期望的方式工作。就我个人而言,我可能会在我自己的代码中使用Ts...方法,因为它更容易理解;但我想有些人会更喜欢decltype方法,因为它看起来表面上更简单,并且受到标准的祝福。对于他自己的每一个。:)