6

有人看过 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);
}

result_of 中的 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

4

1 回答 1

1

您想问的问题可能与这个问题重复:为什么 std::result_of 将(不相关的)函数类型作为类型参数?

让我们剖析一下:

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和返回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是函数类型不能从函数中返回:

typedef int F(char);
std::result_of<F(char)>;  // fails to compile

正如@Simple 在评论中所写,std::result_of<F(Ts...)>::type总是可以用不那么聪明但也不那么混乱的表达来代替

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

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

于 2014-01-22T06:54:17.140 回答