我想把一个类型列表的编译时列表转换成一个std::integral_constant
索引列表的列表。显然,这需要某种类似2d的变换。
示例来源
template<typename... Ts> struct type_list{};
using L = type_list<
type_list<>,
type_list<>,
type_list<>,
type_list<>,
type_list<int>,
type_list<>,
type_list<int>,
type_list<int>,
type_list<int>,
type_list<int,double>,
type_list<int,double>
>;
预期结果
template<uint64_t V> using I = std::integral_constant<uint64_t, V>; // alias for better legibility
using R = type_list<
type_list<>,
type_list<>,
type_list<>,
type_list<>,
type_list<I<0>>,
type_list<>,
type_list<I<1>>,
type_list<I<2>>,
type_list<I<3>>,
type_list<I<4>, I<5>>,
type_list<I<6>, I<7>>
>;
我认为boost::mp11
完全符合这个目的,但我缺乏将这一切结合在一起的经验。请分享您的建议。
3条答案
按热度按时间wlwcrazw1#
我认为boost::mp 11完全符合这个目的,但我缺乏将这一切结合在一起的经验。请分享您的建议。
你说得对!Boost.Mp11确实非常适合这个目的。
这基本上是一个有状态的折叠。我们必须记录到目前为止我们已经推送了多少个值,称之为
N
。然后,对于我们正在迭代的列表中的每个新元素L
,我们附加一个新的列表[N, N+1, ..., N+len(L)-1]
,然后在状态中执行N += len(L)
。为了方便起见,我们可以添加一个
State
:一个累加函数,它执行我上面描述的操作:
最后,我们执行
fold
,并拉出list
:Example证明它做了正确的事情。
but5z9lq2#
下面是一个使用纯C++20的解决方案。
首先是一个小助手,用于将类型前置到类型列表中:
我们的主要切入点是这样的:
我们将递归地对列表进行索引,因此需要一个
List
为空的基本情况:现在是递归专门化。由于我们有两个递归级别(外部列表和内部列表),我们将编写一个
index_inner
助手,它执行内部索引,并返回它使用的最后一个索引:index_inner
的主模板,它不是用尾递归构建,而是在运行时构建列表,这样它就可以跟踪索引(你也可以用尾递归来构建,然后反转列表):完成后,我们将公开max索引和构建的类型列表:
最后,递归的情况:
然后我们可以使用
index<L>::type
得到R
。现场演示:https://godbolt.org/z/KT1dEMs5q
cngwdvgl3#
这里有另一种选择
基本思想是转换以下内容:
进入:
然后应用算法:
获得:
最后将结果转换回
Demo