For silly reasons I\'ll not go into here, I need the commented out line to work and the line above it it to not work:
template
I've made my code work a little bit like lists in Haskell - because, well, TMP is purely functional language inside C++.
add_to_pack
is equivalent to Haskell's list constructor (:)
. drop_from_end
is implemented as (in Haskell notation) \x list -> take (length list - x) list
, where take n
just takes first n
elements of the list.
I suppose you could use std::tuple
directly instead of pack
, but I liked this solution better, because it doesn't misuse tuple as template parameter pack holder. :)
Here's the code:
#include
#include // for std::conditional
template
struct pack
{ };
template
struct add_to_pack;
template
struct add_to_pack>
{
typedef pack type;
};
template
struct convert_to_tuple;
template
struct convert_to_tuple>
{
typedef std::tuple type;
};
template
struct take;
template
struct take
{
typedef pack<> type;
};
template
struct take
{
typedef
typename std::conditional<
(N > 0),
typename add_to_pack<
Head,
typename take<
N - 1,
Tail...
>::type
>::type,
pack<>
>::type type;
};
template
struct drop_from_end
{
// Add these asserts if needed.
//static_assert(N >= 0,
// "Cannot drop negative number of elements!");
//static_assert(N <= static_cast(sizeof...(A)),
// "Cannot drop more elements than size of pack!")
typedef
typename convert_to_tuple<
typename take<
static_cast(sizeof...(A)) - N,
A...
>::type
>::type type;
};
int main()
{
drop_from_end<2, const char*, double, int, int>::type b{"pi", 3.1415};
}
And here's the code at work: via ideone.com.
The take
struct is more or less equivalent to following Haskell code:
take n [] = []
take n (x:xs)
| n > 0 = x : take (n - 1) xs
| otherwise = []