将序列的mpl序列转换为trie

Nim*_*Nim 5 c++ templates boost boost-mpl template-meta-programming

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

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;
Run Code Online (Sandbox Code Playgroud)

我想做的是将其转换为trie,最终结果如下:

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>
            >
          >
        >
      >
    >
  >
>
Run Code Online (Sandbox Code Playgroud)

所以,问题是,这是否可能(我认为不是)?如果有可能,我错过了哪些黑暗法术?

编辑:在情况下,从序列的序列中的上述变换到一个线索是不明确的,让我看看是否可以用简单的英语(通常更为困难.)基本上是主序列中的每个序列由某些类型的(STATE它_1,_2等.)转换后的版本是trie,其中公共前缀被折叠.可能是附图有助于..

结果树

EDIT2:感谢@Yakk,希望现在问题更清楚......

Luc*_*lle 6

你去:

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 >
    >
{};
Run Code Online (Sandbox Code Playgroud)

insertInTrie_impl是一个递归元函数,使用迭代器将序列插入到现有的trie中.insertInTrie接受一个序列和一个电话insertInTrie_impl.constructTrie适用insertInTrie于给定序列中的所有序列,从空的trie开始.

在伪代码中,其内容如下:

Trie insertInTrie_impl(trie, first, last)
{
    if (first == last)
    {
        trie.insert(Terminal, Terminal);
        return trie;
    }

    key = *first;

    subTrie = trie[key];
    if (subTrie = void) // key not found
    {
        subTrie = emptyTrie;
    }

    trie.insert(key, insertInTrie_impl(subTrie, ++first, last))

    return trie;
}

Trie insertInTrie(trie, seq)
{
    return insertInTrie_impl(trie, seq.begin(), seq.end();
}

Trie constructTrie(seqOfSeq)
{
    return fold(seqOfSeq, emptyTrie, insertInTrie);
}
Run Code Online (Sandbox Code Playgroud)

最后,样本使用:

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
        > ));
}
Run Code Online (Sandbox Code Playgroud)