问题看起来很简单,基本上我有一系列序列,如:
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;
我想做的是将其转换为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>
>
>
>
>
>
>
>
所以,问题是,这是否可能(我认为不是)?如果有可能,我错过了哪些黑暗法术?
编辑:如果从序列序列到trie的上述转换不明确,让我看看我是否可以用简单的英语说明(通常更难)。主要序列中的每个序列基本上由一些类型组成(_1
,_2
等。转换后的版本是trie,其中共同的前缀被折叠。可能是附图有帮助..
EDIT2:感谢@Yakk,希望现在问题更加明确......
答案 0 :(得分: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 >
>
{};
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);
}
最后,使用示例:
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
> ));
}
答案 1 :(得分:1)
所以答案是“是的,这是可能的”。
写add_to_trie。它需要一个可能为空的trie和一个元素(一系列类型)并返回一个添加了该元素的trie。
测试一个空的trie和一些序列的add_to_trie,以及一些其他手工制作的案例。公共前缀:(“A”)(“A”,“B”),没有公共前缀:(“A”,“A”)(“B”,“A”),较短没有公共前缀:(“A” ,“B”)(“B”),同一件事的两个副本:(“A”)(“A”)等
写累积。它需要一个值和一个二元仿函数和一个序列。如果在序列的每个元素s上应用value = functor(value,s),则返回值。
通过将1到5相加并打印结果来测试累积。
撰写两个。
这可能会破坏你的模板递归堆栈,并且每个步骤都是非常简单的,但是它可以正常工作。但是它会起作用。
首先在字符串上编写上述操作可能会有所帮助。然后使功能起作用。然后转换为对类型进行操作。
我甚至打赌boost
已经写好了accumulate
的钱。