模板元编程:为什么扁平类型失败

fe2*_*263 5 c++ templates c++11

我想将树型扁平化为扁平型.例:

typedef std::tuple<int,std::tuple<int,long>,int> tup; 
Flat<tup>::type=>std::tuple<int,int,long,int>
Run Code Online (Sandbox Code Playgroud)

我用:

template<typename T>
struct Flat
{
    using type=T;
};
template <template <typename ...> class C,typename...ARGS>
struct Flat<C<ARGS...> >
{
    using type=C<ARGS...>;
};
template <template <typename ...> class C,typename ...ARGS0,typename...ARGS1,typename ...ARGS2>
struct Flat<C<ARGS0...,C<ARGS1...>,ARGS2...> >
:Flat<C<ARGS0...,ARGS1...,ARGS2...> >
{

};

void test(){
typedef std::tuple<int,std::tuple<int,long>,int> tup;
static_assert(std::is_same<typename Flat<tup>::type,std::tuple<int,int,long,int> >::value,"");
}
Run Code Online (Sandbox Code Playgroud)

但我std::tuple<int,std::tuple<int,long>,int>还是静止...我使用gcc 4.8.1

Yak*_*ont 3

这是我的尝试。我试图记录正在发生的事情以使其清楚:

我们从展平开始。它需要一个类型。我们将在下面专门介绍它:

template<typename T>
struct Flatten;
Run Code Online (Sandbox Code Playgroud)

这是我们的主力。获取 Src,展平其内容并将其附加到 Dest:

template<typename Dest, typename Src>
struct Flatten_append;
Run Code Online (Sandbox Code Playgroud)

空的右侧包意味着返回左侧:

template<template<typename...>class Pack, typename... LHS>
struct Flatten_append< Pack<LHS...>, Pack<> > {
  typedef Pack<LHS...> type;
};
Run Code Online (Sandbox Code Playgroud)

第一个参数是 Pack<...> 的右侧应在处理之前展平:

template<template<typename...>class Pack, typename... LHS, typename... RHS0, typename... RHSrest>
struct Flatten_append< Pack<LHS...>, Pack<Pack<RHS0...>, RHSrest... > >:
  Flatten_append< Pack<LHS...>, Pack< RHS0..., RHSrest... > >
{};
Run Code Online (Sandbox Code Playgroud)

否则,非空的右侧包应将其第一个元素移至左侧:(这将比上面的匹配弱,因为它不太专业)

template<template<typename...>class Pack, typename... LHS, typename RHS0, typename... RHSrest>
struct Flatten_append< Pack<LHS...>, Pack<RHS0, RHSrest... > >:
  Flatten_append< Pack<LHS..., RHS0>, Pack< RHSrest... > >
{};
Run Code Online (Sandbox Code Playgroud)

根据 Flatten_append 到空 Pack 的方式实现 Flatten:

template<template<typename...>class Pack, typename... Ts>
struct Flatten< Pack<Ts...> >:Flatten_append< Pack<>, Pack<Ts...> > {};
Run Code Online (Sandbox Code Playgroud)

目标是尽可能清楚地说明正在发生的事情。

现在,您会注意到此设计的一个缺点是它会展平任何 template仅包含类型的内容。我们可能想传递我们想要压平的包。

template<template<typename...>class Pack, typename T>
struct Flatten;

template<template<typename...>class Pack, typename Dest, typename Src>
struct Flatten_append;

template<template<typename...>class Pack, typename... Ts>
struct Flatten< Pack<Ts...> > : Flatten_append< Pack, Pack<>, Pack<Ts...> > {};
Run Code Online (Sandbox Code Playgroud)

然后将每个专业更改Flatten_append< blah, blah, blah >Flatten_append< Pack, blah, blah, blah >

这意味着您明确传入template要展平的 ,并且代码仅展平该template

实际上,这可能不需要,因为Pack类型是从传入的左侧类型推导出来的。