私のコードは、Haskell のリストのように機能するようにしました。なぜなら、TMP は C++ 内の純粋な関数型言語だからです。
add_to_pack
Haskell の list constructor と同等(:)
です。drop_from_end
は (Haskell 記法で) として実装され\x list -> take (length list - x) list
、リストのtake n
最初のn
要素のみを取ります。
std::tuple
の代わりに直接使用できると思いますがpack
、タプルをテンプレートパラメーターパックホルダーとして誤用しないため、このソリューションの方が気に入りました。:)
コードは次のとおりです。
#include <tuple>
#include <type_traits> // for std::conditional
template <typename... Pack>
struct pack
{ };
template <typename, typename>
struct add_to_pack;
template <typename A, typename... R>
struct add_to_pack<A, pack<R...>>
{
typedef pack<A, R...> type;
};
template <typename>
struct convert_to_tuple;
template <typename... A>
struct convert_to_tuple<pack<A...>>
{
typedef std::tuple<A...> type;
};
template <int, typename...>
struct take;
template <int N>
struct take<N>
{
typedef pack<> type;
};
template <int N, typename Head, typename... Tail>
struct take<N, Head, Tail...>
{
typedef
typename std::conditional<
(N > 0),
typename add_to_pack<
Head,
typename take<
N - 1,
Tail...
>::type
>::type,
pack<>
>::type type;
};
template <int N, typename... A>
struct drop_from_end
{
// Add these asserts if needed.
//static_assert(N >= 0,
// "Cannot drop negative number of elements!");
//static_assert(N <= static_cast<int>(sizeof...(A)),
// "Cannot drop more elements than size of pack!")
typedef
typename convert_to_tuple<
typename take<
static_cast<int>(sizeof...(A)) - N,
A...
>::type
>::type type;
};
int main()
{
drop_from_end<2, const char*, double, int, int>::type b{"pi", 3.1415};
}
そして、これが作業中のコードです: via ideone.com .
このtake
構造体は、次の Haskell コードとほぼ同等です。
take n [] = []
take n (x:xs)
| n > 0 = x : take (n - 1) xs
| otherwise = []