std::make_index_sequence的簡單實現和簡單應用
前言
之前翻cpp-reference翻到一個有趣的東西:
sequence其中有一條
template<class T, T N>nusing make_integer_sequence = std::integer_sequence<T, /* a sequence 0, 1, 2, ..., N-1 */ >;n
起初沒有仔細想,以為這種將一個參數N拆出N個元函數參數的效果是靠編譯器開洞實現的,像std::declval那樣,只有申明沒有定義,後來在某個應用場景下用到了這玩意,又仔細考慮了一下,發現這玩意其實是可以實現的,下面給一個簡單的實現。
正文
首先定義sequence
template<size_t...I>nstruct seq {ntusing type = seq;n};n
然後是concat,用以將兩個sequence拆包再拼起來,因為處理目標是實現make_index_sequence<N>,所以這裡和一般的concat不太一樣,直接把1到N-1的計算也放進去了
template<class... I>nstruct concat;nntemplate<size_t L, size_t...H>nstruct concat<seq<L>, seq<H...>> : public seq<L, (H + 1)...> {n};n
最後是make
template<size_t N>nstruct make : public concat<seq<0>, typename make<N-1>::type> {n};nntemplate<>nstruct make<1> : public seq<0> {n};nntemplate<>nstruct make<0> : public seq<> {n};n
測試一下:
template<size_t N, size_t F, size_t...I>nconstexpr size_t get(seq<F, I...> q) {ntif constexpr (N == 0) {nttreturn F;nt} else {nttreturn get<N - 1>(seq<I...>{});nt}n}nnvoid make_test() {ntauto seq = make<4>{};ntstatic_assert(get<0>(seq) == 0, "");ntstatic_assert(get<1>(seq) == 1, "");ntstatic_assert(get<2>(seq) == 2, "");ntstatic_assert(get<3>(seq) == 3, "");n}n
簡單的使用
C++標準給出這樣一個東西肯定是有用的,那麼怎麼用呢?最簡單的可以用來迭代。
比如你有一個函數,作用是將傳入的tuple的每一個元素加上1再返回
template<class... TList>nstd::tuple<TList...> succ(std::tuple<TList...> tup) {nt// how to add it?n}n
有了make_sequence之後你可以這樣:
template<class Sequence>nstruct succ_impl;nntemplate<size_t...I>nstruct succ_impl<seq<I...>> {nttemplate<class...TList>ntstatic constexpr decltype(auto) apply(std::tuple<TList...> arg) {nttreturn std::make_tuple( (std::get<I>(arg) + 1)... );nt}n};nntemplate<class... TList>nconstexpr std::tuple<TList...> succ(std::tuple<TList...> arg) {ntreturn succ_impl<typename make<sizeof...(TList)>::type>::apply(arg);n}n
簡單的測試一下:
void succ_test() {ntconstexpr std::tuple<int, int, int, int> tup(1, 2, 0, 4);ntconstexpr auto new_tup = succ(tup);nntstatic_assert(std::get<0>(new_tup) == 2, "");ntstatic_assert(std::get<1>(new_tup) == 3, "");ntstatic_assert(std::get<2>(new_tup) == 1, "");ntstatic_assert(std::get<3>(new_tup) == 5, "");n}n
推薦閱讀:
※GacUI:初步完成Workflow腳本轉C++的工作
※《C++ Primer》讀書筆記-第七章 06 類的靜態成員
※Roman To Integer
※【源碼眾讀】之問題解答,Part_3
