创建具有MPL所有模板排列 [英] Creating all template permutations with MPL

查看:99
本文介绍了创建具有MPL所有模板排列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下的模板类结构

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

主机类可现在怎么有以下几种类型。

The Host class can now how have the following types.

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;

有什么方法来创建的boost :: MPL类型列表?目前,我甚至不有一个想法从哪里开始。
我的目标是将有这样的功能:

Is there any way to create a type list with boost::mpl? At the moment I don't even have an Idea where to start. My Goal would be to have a function like this:

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

这可能与升压:: MPL?

Is this possible with boost::mpl?

推荐答案

确定这里是一些实现。这是相当特设的,我们可以很明显的抽象其采取的lambda功能序列的序列,但我preferred保持此一条直线。评论和测试都在里面:

Ok here is some implementation. It is rather ad-hoc, one could obviously abstract it to take a sequence of sequence of lambda function, but I preferred keeping this one straight. Comments and tests are inside:

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

预期的输出应该是:

The expected output should be :

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>>>

这篇关于创建具有MPL所有模板排列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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