Search code examples
c++boostvariadic-templatesboost-mpl

boost mpl sequence pattern matching


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


Solution

  • 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.