元编程中有时候会需要容器已容纳暂时的数据。已经在模板元编程上卷了一周,结果发现这种编程方式有提高运行效率的作用,但是在编译时间长、执行文件大、编程复杂的缺点下实在是非常鸡肋,除了炫技几乎可以说毫无作用。所以就炫技一下,以下实现了一种支持插入、连接、交换元素的类模板,本意是用来进一步写行列式求值运算的。代码如下:
template<int...is>
struct container
{
template<int N, int itr, int topop, int... remains>
static constexpr int get_cal = get_cal<N, itr + 1, remains...>;
template<int N, int ret, int...remains>
static constexpr int get_cal<N, N, ret, remains...> = ret;
template<int N>
static constexpr int get = get_cal<N, 0, is...>;
static constexpr int size = sizeof...(is);
template<int i> using push_back = container<is..., i>;
template<int i> using push_front = container<i, is...>;
template<int total_N, int cur_N, typename other>
struct st_push_other_back
{
using t_next = push_back < other::template get<cur_N>>;
using ret = typename t_next::template st_push_other_back<total_N, cur_N + 1, other>::ret;
};
template<int N, typename other>
struct st_push_other_back<N, N, other>
{
using ret = container<is...>;
};
template<typename other>
using push_other_back = typename st_push_other_back<other::size, 0, other>::ret;
template<int N, int top, int...remains>
struct n_cal
{
using t_front = typename n_cal<N - 1, remains...>::t_front::template push_front<top>;
using t_after = typename n_cal<N - 1, remains...>::t_after;
};
template<int top, int...remains>
struct n_cal<1, top, remains...>
{
using t_front = container<top>;
using t_after = container<remains...>;
};
/* 当is时空的时候短路n_cal运算 */
template<bool b, int N>
struct enable_cal
{
using front = typename n_cal<N, is...>::t_front;
using after = typename n_cal<N, is...>::t_after;
};
template<int N>
struct enable_cal<false, N>
{
using front = container<>;
using after = container<>;
};
template<int N>
using front_n = typename enable_cal<sizeof...(is)!=0, N>::front;
template<int N>
using after_n = typename enable_cal<sizeof...(is) != 0, N>::after;
template<int N, int M>
using mid_nm = typename front_n<M>::template after_n<N>;
template<int N, int M>
struct swap_cal
{
using swap_front = front_n<N>;
using swap_mid = mid_nm<N + 1, M>;
using swap_after = after_n<M + 1>;
using ret = typename swap_front::template push_back<get<M>>::template push_other_back<swap_mid>::template push_back<get<N>>::template push_other_back<swap_after>;
};
template<int N, int M>
using swap = typename swap_cal<N, M>::ret;
};
下面采用一个测试程序来验证这种模板的有效性:
/* 生成序列 */
template<int N, int cur_i, int... is>
struct gen_seq
{
using t = typename gen_seq<N, 1+cur_i, is..., cur_i>::t;
};
template<int N, int... is>
struct gen_seq<N, N, is...>
{
using t = container<is...>;
};
template<int N>
using gen_seq_t = typename gen_seq<N, 0>::t;
int main()
{
gen_seq_t<10>::push_other_back<gen_seq_t<2>> k;
decltype(k)::mid_nm<1, 10>::swap<1,2> j;
int i = k.get<3>;
int ik = k.get<k.size-1>;
_getch();
return 0;
}
通过调试,可以发现k的类型为container<0,1,2,3,4,5,6,7,8,9,0,1>。可见已经将container<0,...,9>和container<0,1>连接了起来。通过get获取到的i等于2,也正确获取对应位置的参数。