I am trying to write a metafunction which (in haskell) looks roughly like:
gather :: [a] -> [a] -> ([a], [a])
gather (x:xs) (_:_:ys) = <something using x, xs, and ys>
...other pattern matches...
I was able to do this using a roll-my-own own variadic template sequence but can't seem to figure out how to do this using mpl.
for simplicity I was trying this sample function (should help me understand what I need):
//get_first :: [a] -> a
template<class SEQ_C>
get_first {
enum { value = -1 };
typedef get_first<SEQ_C> type;
};
//get_first (x:xs) = x
template<template<class T, T... S> class SEQ_C, class T, T x, T... xs>
struct get_first<SEQ_C<T, x, xs...>> {
enum { value = x };
typedef get_first<SEQ_C<T, x, xs...>> type;
};
...
typedef boost::mpl::vector_c<int 1, 2, 3> listA;
typedef get_first<listA>::type first;
std::cout << first::value << std::endl;
outputs -1.
I have tried a number of different ways of getting a match at this point I am just taking stabs in the dark. The documentation makes it seem like mpl::vector_c<int, x>
is actually a list of integral_c<int, x>
-- but attempt to use this result is other errors.
Maybe pattern matching
Wow, I find the root of the problem. Look at the error message(you could see it if you comment typedef get_first<SEQ_C> type;
line):
error: ‘type’ in ‘struct get_first<boost::mpl::vector_c<int, 1l, 2l, 3l> >’ does not name a type
// ^ ^ ^
As you can see, g++
interprets passed arguments as long
, not as int
. So, if you change your specification to:
template<template<class T, long... S> class SEQ_C, class T, long x, long... xs>
struct get_first<SEQ_C<T, x, xs...>> {
enum { value = x };
typedef get_first<SEQ_C<T, x, xs...>> type;
};
It would work.
Of course, it is not a solution, I just show, how it would work. I think, it's bug in g++, since clang++ produces 1
for your code.