C++ 使用MPL创建所有模板置换

C++ 使用MPL创建所有模板置换,c++,boost,metaprogramming,boost-mpl,C++,Boost,Metaprogramming,Boost Mpl,我有以下模板化的类结构 struct TraitA{}; struct TraitB{}; template<typename trait> struct FunctionalityA{}; template<typename trait> struct FunctionalityB{}; template<typename Func> struct FuncUserA{}; template<typename Func> struct F

我有以下模板化的类结构

struct TraitA{};
struct TraitB{};

template<typename trait>
struct FunctionalityA{};

template<typename trait>
struct FunctionalityB{};

template<typename Func>
struct FuncUserA{};

template<typename Func>
struct FuncUserB{};

template<typename fuser>
struct Host{};
struct TraitA{};
结构TraitB{};
模板
结构功能a{};
模板
结构功能b{};
模板
结构FuncUserA{};
模板
结构FuncUserB{};
模板
结构主机{};
Host类现在可以具有以下类型

typedef Host<FuncUserA<FunctionalityA<TraitA> > > Host1_t;
typedef Host<FuncUserA<FunctionalityA<TraitB> > > Host2_t;
typedef Host<FuncUserA<FunctionalityB<TraitA> > > Host3_t;
typedef Host<FuncUserA<FunctionalityB<TraitB> > > Host4_t;
typedef Host<FuncUserB<FunctionalityA<TraitA> > > Host5_t;
typedef Host<FuncUserB<FunctionalityA<TraitB> > > Host6_t;
typedef Host<FuncUserB<FunctionalityB<TraitA> > > Host7_t;
typedef Host<FuncUserB<FunctionalityB<TraitB> > > Host8_t;
typedef主机主机1\u t;
typedef主机主机2_t;
typedef主机3_t;
typedef主机4_t;
typedef主机5_t;
typedef主机主机6_t;
typedef主机7_t;
typedef主机8_t;
有没有办法用boost::mpl创建类型列表?现在我甚至不知道从哪里开始。 我的目标是实现如下功能:

template<class T>
T* getHost()
{
  typedef boost::mpl::find<HostVector, T>::type MplIter;
  return new MplIter;
}
模板
T*getHost()
{
typedef boost::mpl::find::type MplIter;
返回新MplIter;
}

这在boost::mpl中可能吗?

好的,下面是一些实现。这是非常特别的,我们可以很明显地把它抽象成一系列的lambda函数,但我更喜欢保持这一点。评论和测试内容如下:

#include <iostream>

////////////////////////////////////////////////////////////////////////////////
// Base types to permute around - added soem display for tests purpose
////////////////////////////////////////////////////////////////////////////////
struct TraitA { TraitA() { std::cout << "TA"; } };
struct TraitB { TraitB() { std::cout << "TB"; } };

template<typename Trait>
struct FunctionalityA
{
  FunctionalityA() { std::cout << "FunctionalityA<"; Trait(); std::cout << ">";}
};

template<typename Trait>
struct FunctionalityB
{
  FunctionalityB() { std::cout << "FunctionalityB<"; Trait(); std::cout << ">";}
};

template<typename Func>
struct FuncUserA
{
  FuncUserA() { std::cout << "FuncUserA<"; Func(); std::cout << ">";}
};

template<typename Func>
struct FuncUserB
{
  FuncUserB() { std::cout << "FuncUserB<"; Func(); std::cout << ">";}
};

template<typename Fuser> struct Host
{
  Host() { std::cout << "Host<"; Fuser(); std::cout << ">\n";}
};

////////////////////////////////////////////////////////////////////////////////
// Step 1 : Make static list of potential options
//
// These lists has to be updated as new Trait, FuncUser and Functionality are
// made.
////////////////////////////////////////////////////////////////////////////////
#include <boost/mpl/vector.hpp>
#include <boost/mpl/placeholders.hpp>

typedef boost::mpl::vector< TraitA, TraitB >              traits_list;
typedef boost::mpl::vector< FunctionalityA<boost::mpl::_>
                          , FunctionalityB<boost::mpl::_>
                          >                                functionalities_list;

typedef boost::mpl::vector< FuncUserA<boost::mpl::_>
                          , FuncUserB<boost::mpl::_>
                          >                                fusers_list;

////////////////////////////////////////////////////////////////////////////////
// Step 1 : Build the types
//
// We want every combination of Trait and Functionality. This is basically a
// cartesian product of traits_list and functionalities_list which is done
// usign nested fold
////////////////////////////////////////////////////////////////////////////////
#include <boost/mpl/fold.hpp>
#include <boost/mpl/copy.hpp>
#include <boost/mpl/push_back.hpp>
#include <boost/mpl/back_inserter.hpp>

template<typename Fusers, typename Functionalities, typename Traits>
struct build_combo
{
  //////////////////////////////////////////////////////////////////////////////
  // Inner fold loop iterating over the traits
  //////////////////////////////////////////////////////////////////////////////
  template<typename FuserFunc>
  struct traits_loop
  {
    template<typename T>
    struct fuse : boost::mpl::apply<FuserFunc,T> {};

    typedef typename
    boost::mpl::fold< Traits
                    , boost::mpl::vector<>
                    , boost::mpl::push_back < boost::mpl::_1
                                            , fuse<boost::mpl::_2>
                                            >
                    >::type type;
  };

  //////////////////////////////////////////////////////////////////////////////
  // Inner fold loop iterating over the functionnality/traits
  //////////////////////////////////////////////////////////////////////////////
  template<typename Fuser>
  struct func_traits_loop
  {
    template<typename T>
    struct fuse : boost::mpl::apply<Fuser,T> {};

    typedef typename
    boost::mpl::fold< Functionalities
                    , boost::mpl::vector<>
                    , boost::mpl::copy< traits_loop< fuse<boost::mpl::_2> >
                                      , boost::mpl::back_inserter<boost::mpl::_1>
                                      >
                    >::type type;
  };

  //////////////////////////////////////////////////////////////////////////////
  // fold loop iterating over the Fuser x {Functionality,Traits}
  // For each Fuser, copy its vector of applications to the others
  //////////////////////////////////////////////////////////////////////////////
  typedef typename
  boost::mpl::fold< Fusers
                  , boost::mpl::vector<>
                  , boost::mpl::copy< func_traits_loop<boost::mpl::_2>
                                    , boost::mpl::back_inserter<boost::mpl::_1>
                                    >
                  >::type type;
};

////////////////////////////////////////////////////////////////////////////////
// Now the get_host meta-function
////////////////////////////////////////////////////////////////////////////////
#include <boost/mpl/at.hpp>

template<int N>
struct get_host
{
  typedef build_combo < fusers_list
                      , functionalities_list
                      , traits_list
                      >::type                     types;
  typedef typename boost::mpl::at_c<types,N>::type hosted;
  typedef Host<hosted> type;
};

////////////////////////////////////////////////////////////////////////////////
// Some tests
////////////////////////////////////////////////////////////////////////////////

int main()
{
  get_host<1>::type x1;
  get_host<2>::type x2;
  get_host<3>::type x3;
  get_host<4>::type x4;
  get_host<5>::type x5;
  get_host<6>::type x6;
  get_host<7>::type x7;
}
#包括
////////////////////////////////////////////////////////////////////////////////
//要排列的基类型-为测试目的添加soem显示
////////////////////////////////////////////////////////////////////////////////
结构TraitA{TraitA(){std::cout
>::类型类型;
};
//////////////////////////////////////////////////////////////////////////////
//在Fuser x{功能,Traits}上迭代的折叠循环
//对于每个Fuser,将其应用程序向量复制到其他Fuser
//////////////////////////////////////////////////////////////////////////////
typedef typename
boost::mpl::fold
>::类型类型;
};
////////////////////////////////////////////////////////////////////////////////
//现在是get_host元函数
////////////////////////////////////////////////////////////////////////////////
#包括
模板
结构获取主机
{
typedef build_组合::类型;
typedef typename boost::mpl::at_c::type hosted;
typedef主机类型;
};
////////////////////////////////////////////////////////////////////////////////
//一些测试
////////////////////////////////////////////////////////////////////////////////
int main()
{
get_host::type x1;
get_host::type x2;
get_host::type x3;
get_host::type x4;
get_host::type x5;
get_host::type x6;
get_主机::类型x7;
}
预期产出应为:

Host<FuncUserA<FunctionalityA<TB>>>
Host<FuncUserA<FunctionalityB<TA>>>
Host<FuncUserA<FunctionalityB<TB>>>
Host<FuncUserB<FunctionalityA<TA>>>
Host<FuncUserB<FunctionalityA<TB>>>
Host<FuncUserB<FunctionalityB<TA>>>
Host<FuncUserB<FunctionalityB<TB>>>
主机
主办
主办
主办
主办
主办
主办
简介 我的答案试图成为C++11用户的首选答案

Joel Falcou的答案对于较旧的标准来说是很好的,但是C++11 参数包通常使boost类型序列过时。此外,我认为在这种情况下,piggy backing模板比使用
boost::lambda
更好。 实际上,我的解决方案除了笛卡尔产品模板之外根本不使用include,我将从中获取该模板,因为它不在标准库中

使用当前最新的功能(从C++11开始)可以编写一个解决方案:

  • 比例更好
  • 它比较短
  • 更具可读性,因为解决方案分离了关注点
  • 解释了不同的模板:
    expand\u pack
    执行其参数。这允许使用省略号重复运行时代码。示例:
    扩展包(新的T{}…
    <有人知道这个成语的名字吗

    wrap\u template\u as\u type
    借助模板,以便在需要类型的地方使用。也许这个习惯用法被称为模板重新绑定或后期模板绑定。 我不知道,所以我把这个问题贴在这里。示例:
    wrap\u template\u as\u type
    和相反的
    wrapper::unwrapp

    type_list
    一个没有数据、铃铛和wissel的元组

    template\u list
    一种模板,它获取模板列表并返回一个类型列表,原始模板放在包装器中

    make_host_type
    A、B、C、D
    转换为
    A

    all_hosts
    获取主机类型的元组,并为输入元组中的每个元素创建一个主机

    完整示例 请注意,
    #包括http://...
    必须替换为链接内容

    请注意,MSVC不理解PRETTY_函数,但我认为函数名

    #include <iostream>
    #include <typeinfo>
    #include https://stackoverflow.com/a/19611856/2712726
    template<typename... Ts> void expand_pack (Ts... t) {}
    
    template <template<typename...> class T>
    struct wrapp_template_as_type {
        template <typename... Us> using unwrapp =  T <Us...>;
    };
    
    template<typename... T> struct type_list {};
    
    template <template<typename...> class... Ts>
    struct template_list {
        using type = type_list< wrapp_template_as_type<Ts>... >;
    };
    
    struct TraitA{}; struct TraitB{}; struct TraitC{}; struct TraitD{}; struct TraitE{}; struct TraitF{};
    template<typename Trait>    struct  WhateverA{};
    template<typename Trait>    struct  WhateverB{};
    template<typename Whatever> struct  FunctionalityA{};
    template<typename Whatever> struct  FunctionalityB{};
    template<typename Whatever> struct  FunctionalityC{};
    template<typename Whatever> struct  FunctionalityD{};
    template<typename Func>     struct  FuncUserA{};
    template<typename Func>     struct  FuncUserB{};
    template<typename Func>     struct  FuncUserC{};
    template<typename FuncUser> struct  Host { Host() {std::cout << __PRETTY_FUNCTION__ << std::endl;}};
    
    template<typename T> struct make_host_type;
    
    template<template<typename...> class List, typename T, typename... Ts>
    struct make_host_type < List<T, Ts...> > {
        using type = typename T::template unwrapp < typename make_host_type< List<Ts...> >::type >;
    };
    
    template<template<typename...> class List, typename T>
    struct make_host_type < List<T> > {
        using type = T;
    };
    
    template <typename T> struct all_hosts;
    
    template <template<typename...> class Hosts, typename... Ts>
    struct all_hosts <Hosts<Ts...> > {
        static void create () {
            expand_pack (new typename make_host_type<Ts>::type{}...);
        }
    };
    
    int main () {
        using a =          type_list     < TraitA, TraitB, TraitC, TraitD, TraitE, TraitF >;
        using b = typename template_list < WhateverA, WhateverB>::type;
        using c = typename template_list < FunctionalityA, FunctionalityB, FunctionalityC, FunctionalityD >::type;
        using d = typename template_list < FuncUserA, FuncUserB, FuncUserC >::type;
        using e = typename template_list < Host >::type;
        using p = typename product<type_list, e, d, c, b, a>::type; // create a type_list of all possible Host types.
        all_hosts<p>::create(); // calls constructor for each Host type
    }
    
    #包括
    #包括
    #包括https://stackoverflow.com/a/19611856/2712726
    模板无效扩展包(Ts…t){
    模板
    结构wrapp\u模板\u作为\u类型{
    使用unwrapp=T的模板;
    };
    模板结构类型_列表{};
    模板
    结构模板列表{
    使用type=type_list;
    };
    结构TraitA{};结构TraitB{};结构TraitC{};struct TraitD{};结构TraitE{};结构TraitF{};
    模板结构WhateverA{};
    模板结构WhateverB{};
    模板结构功能a{};
    模板结构功能b{};
    模板结构功能{};
    模板结构功能{};
    模板结构FuncUserA{};
    模板结构FuncUserB{};
    模板结构FuncUserC{};
    模板结构主机{Host(){std::cout::type>;
    };
    模板
    结构生成主机类型<列表>{
    使用类型=T;
    };
    所有_主机的模板结构;
    模板
    结构所有_主机{
    静态void创建(){
    展开_-pack(新类型名make_-host_-type::type{};
    }
    };
    int main(){
    使用a=type_list;
    使用b=typename模板_list::type;
    使用c=typename模板\u列表Host<FuncUser>::Host() [with FuncUser = FuncUserC<FunctionalityD<WhateverB<TraitF> > >]
    Host<FuncUser>::Host() [with FuncUser = FuncUserB<FunctionalityD<WhateverB<TraitF> > >]
    Host<FuncUser>::Host() [with FuncUser = FuncUserA<FunctionalityD<WhateverB<TraitF> > >]
    Host<FuncUser>::Host() [with FuncUser = FuncUserC<FunctionalityC<WhateverB<TraitF> > >]
    Host<FuncUser>::Host() [with FuncUser = FuncUserB<FunctionalityC<WhateverB<TraitF> > >]
    Host<FuncUser>::Host() [with FuncUser = FuncUserA<FunctionalityC<WhateverB<TraitF> > >]
    Host<FuncUser>::Host() [with FuncUser = FuncUserC<FunctionalityB<WhateverB<TraitF> > >]
    Host<FuncUser>::Host() [with FuncUser = FuncUserB<FunctionalityB<WhateverB<TraitF> > >]
    ...
    Host<FuncUser>::Host() [with FuncUser = FuncUserA<FunctionalityA<WhateverA<TraitA> > >]