C++ 将mpl序列转换为trie

C++ 将mpl序列转换为trie,c++,templates,boost,template-meta-programming,boost-mpl,C++,Templates,Boost,Template Meta Programming,Boost Mpl,问题看起来很简单,基本上我有一系列的序列,比如: typedef mpl::vector< mpl::vector<mpl::_1, mpl::_2>, mpl::vector<mpl::_1, mpl::_2, mpl::_3>, mpl::vector<mpl::_2, mpl::_1>, mpl::vector<mpl::_2, mpl::_2>, mpl::vector<mpl::_2, mpl::_2, m

问题看起来很简单,基本上我有一系列的序列,比如:

typedef mpl::vector<
  mpl::vector<mpl::_1, mpl::_2>,
  mpl::vector<mpl::_1, mpl::_2, mpl::_3>,
  mpl::vector<mpl::_2, mpl::_1>,
  mpl::vector<mpl::_2, mpl::_2>,
  mpl::vector<mpl::_2, mpl::_2, mpl::_3>
> seq;
mpl::map<
  mpl::pair<mpl::_1, 
    mpl::map<
      mpl::pair<mpl::_2,
        mpl::map<
          mpl::pair<TERMINAL, T>,
          mpl::pair<mpl::_3,
            mpl::map<
              mpl::pair<TERMINAL, T>
            >
          >
        >
      >
    >
  >
  mpl::pair<mpl::_2, 
    mpl::map<
      mpl::pair<mpl::_1,
        mpl::map<
          mpl::pair<TERMINAL, T>
        >
      >,
      mpl::pair<mpl::_2,
        mpl::map<
          mpl::pair<TERMINAL, T>,
          mpl::pair<mpl::_3,
            mpl::map<
              mpl::pair<TERMINAL, T>
            >
          >
        >
      >
    >
  >
>
typedef mpl::vector<
向量,
向量,
向量,
向量,
向量
>序号;
我想做的是将其转换为trie,最终结果如下:

typedef mpl::vector<
  mpl::vector<mpl::_1, mpl::_2>,
  mpl::vector<mpl::_1, mpl::_2, mpl::_3>,
  mpl::vector<mpl::_2, mpl::_1>,
  mpl::vector<mpl::_2, mpl::_2>,
  mpl::vector<mpl::_2, mpl::_2, mpl::_3>
> seq;
mpl::map<
  mpl::pair<mpl::_1, 
    mpl::map<
      mpl::pair<mpl::_2,
        mpl::map<
          mpl::pair<TERMINAL, T>,
          mpl::pair<mpl::_3,
            mpl::map<
              mpl::pair<TERMINAL, T>
            >
          >
        >
      >
    >
  >
  mpl::pair<mpl::_2, 
    mpl::map<
      mpl::pair<mpl::_1,
        mpl::map<
          mpl::pair<TERMINAL, T>
        >
      >,
      mpl::pair<mpl::_2,
        mpl::map<
          mpl::pair<TERMINAL, T>,
          mpl::pair<mpl::_3,
            mpl::map<
              mpl::pair<TERMINAL, T>
            >
          >
        >
      >
    >
  >
>
mpl::map<
mpl::pair
>
>
>
mpl::pair,
mpl::pair
>
>
>
>
>
所以,问题是,这可能吗(我认为不可能)?如果可能的话,我错过了哪些黑暗咒语

编辑:如果上述从序列序列到trie的转换不清楚,让我看看是否可以用简单的英语来说明(通常更难)。基本上,主序列中的每个序列都由一些类型组成(
\u 1
\u 2
等)。转换后的版本是trie,其中常见前缀被折叠。附件中的图片可能有帮助

编辑2:感谢@Yakk,希望现在问题更清楚了…

所以答案是“是的,这是可能的”

将添加内容写入目录。它接受一个可能为空的trie和一个元素(一系列类型),并返回一个添加了该元素的trie

在一个空的trie和一些序列上,以及在一些其他手工制作的情况下,测试add_to_trie。通用前缀:(“A”)(“A”、“B”)、无通用前缀:(“A”、“A”)(“B”、“A”)、较短的无通用前缀:(“A”、“B”)(“B”)、同一事物的两份副本:(“A”)(“A”)等

写积累。它接受一个值、一个二进制函子和一个序列。如果对序列的每个元素s应用value=functor(value,s),则返回value

通过将1到5相加并打印结果来累积测试

把两者组合起来

这可能会破坏模板递归堆栈,每个步骤都很容易编写正确,但它会工作

首先在字符串上编写上述操作可能会有所帮助。然后使功能正常运行。然后转换为对类型进行操作

我敢打赌,即使是钱,
boost
也有一个合适的
累加

好了:

struct Terminal;

template < typename Trie, typename First, typename Last,
           typename Enable = void >
struct insertInTrie_impl
{
    typedef typename
        mpl::deref<First>::type key;

    typedef typename 
        mpl::at<
            Trie,
            key
        >::type subTrieOrVoid; // would be easier if "at" supported Default

    typedef typename
        mpl::if_<
            boost::is_same< subTrieOrVoid, mpl::void_ >,
            mpl::map<>,
            subTrieOrVoid
        >::type subTrie;

    typedef typename
        mpl::insert<
            Trie,
            mpl::pair<
                key, typename
                insertInTrie_impl<
                    subTrie, typename
                    mpl::next<First>::type,
                    Last
                >::type
            >
        >::type type;
};

template < typename Trie, typename First, typename Last >
struct insertInTrie_impl< Trie, First, Last, typename 
    boost::enable_if< boost::is_same<First, Last> >::type >
    : mpl::insert<
        Trie,
        mpl::pair< Terminal, Terminal >
        // I'm not sure what you want in your terminal node
    >
{};

template < typename Trie, typename Seq >
struct insertInTrie
    : insertInTrie_impl< 
        Trie, typename 
        mpl::begin<Seq>::type, typename 
        mpl::end<Seq>::type
    >
{};


template < typename SeqOfSeq >
struct constructTrie
    : mpl::fold< 
        SeqOfSeq,
        mpl::map<>,
        insertInTrie< mpl::_1, mpl::_2 >
    >
{};
最后,使用以下示例:

int main()
{
    typedef mpl::vector<
        mpl::vector<mpl::_1, mpl::_2>,
        mpl::vector<mpl::_1, mpl::_2, mpl::_3>,
        mpl::vector<mpl::_2, mpl::_1>,
        mpl::vector<mpl::_2, mpl::_2>,
        mpl::vector<mpl::_2, mpl::_2, mpl::_3>
    > seqOfSeq;

    typedef constructTrie< seqOfSeq >::type bigTrie;

    BOOST_MPL_ASSERT(( 
        mpl::has_key<
            mpl::at< 
                mpl::at< 
                    bigTrie, 
                    mpl::_1
                >::type, 
                mpl::_2
            >::type, 
            Terminal
        > ));
    BOOST_MPL_ASSERT(( 
        mpl::has_key<
            mpl::at< 
                mpl::at< 
                    mpl::at< 
                        bigTrie, 
                        mpl::_1
                    >::type,
                    mpl::_2
                >::type, 
                mpl::_3
            >::type, 
            Terminal
        > ));
    BOOST_MPL_ASSERT(( 
        mpl::has_key<
            mpl::at< 
                mpl::at< 
                    bigTrie, 
                    mpl::_2
                >::type,
                mpl::_2
            >::type, 
            Terminal
        > ));
}
intmain()
{
typedefmpl::vector<
向量,
向量,
向量,
向量,
向量
>seqOfSeq;
typedef-constructrie:类型bigTrie;
增强MPL断言((
mpl::具有\u密钥<
mpl::at<
mpl::at<
比格特里,
mpl::_1
>::类型,
mpl::_2
>::类型,
终点站
> ));
增强MPL断言((
mpl::具有\u密钥<
mpl::at<
mpl::at<
mpl::at<
比格特里,
mpl::_1
>::类型,
mpl::_2
>::类型,
mpl::_3
>::类型,
终点站
> ));
增强MPL断言((
mpl::具有\u密钥<
mpl::at<
mpl::at<
比格特里,
mpl::_2
>::类型,
mpl::_2
>::类型,
终点站
> ));
}

我看不出您想要的转换是什么。请提供实际的具体示例和伪代码。@Yakk,已更新-这有帮助吗?基本上,我试图在图片中构建给定的树,这样我就可以使用给定的序列(
mpl::vector
来获取
终端
类型的实例)进行导航。如果缺少子序列1和4,结构是否与生成的结构等效?如果我理解正确,主序列是一个路径序列,节点是在尚未出现时生成的(路径
mpl::vector
mpl::vector
缺失)@AndyProwl,最终结果应该允许您查找任何给定序列以获得
terminal
类型,如果缺失,我不明白这怎么可能?@Nim:我想知道的是,从主序列中删除第一个和第四个序列是否会产生相同的结果。在我看来,这些序列是多余的,还是不是?如果没有,为什么
mpl::vector
mpl::vector
也不存在呢?
boost
确实提供了
累积
,我想我现在的问题是如何将咒语按正确的顺序排列以获得最终结果…+1,这将花费我一天的时间来解决这个问题!;)@尼姆:一旦你习惯了元函数的工作方式,其实没那么难。我添加了一些伪代码,以一种更简单的方式解释mpl代码。很好,我实现了这一点,终端类型可以作为最后一个参数在嵌套序列中传递,我只需添加另一个间接寻址,将其从序列中剥离并传播。再次感谢!