So with the help given I was able to come up with something that seems to work. It requires one specialization with long that is used for char, short, int, long types, and the original template for use with long long.
So the final template looks like this:
// get_first :: [a] -> a
// get_first x:xs = x
template<class SEQ_C>
struct get_first {
enum { value = -1 };
typedef get_first<SEQ_C> type;
typedef typename SEQ_C::value_type value_type;
typedef SEQ_C sequence_type;
};
//needed for char/short/int/long
template<template<class T, long... S> class SEQ_C, class T0, long X, long... XS>
struct get_first<SEQ_C<T0, X, XS...>> {
enum { value = X };
typedef get_first<SEQ_C<T0, X, XS...>> type;
typedef T0 value_type;
typedef SEQ_C<T0, X, XS...> sequence_type;
};
//needed for long long
template<template<class T, T... S> class SEQ_C, class T0, T0 X, T0... XS>
struct get_first<SEQ_C<T0, X, XS...>> {
enum { value = X };
typedef get_first<SEQ_C<T0, X, XS...>> type;
typedef T0 value_type;
typedef SEQ_C<T0, X, XS...> sequence_type;
};
demangling the get_first<SEQ>::sequence_type
was quite revealing. To that end I found this bit of code quite useful (if you don't feel like using c++filt all the time):
#include<typeinfo>
#include<string>
#include<cstdlib>
#include<cxxabi.h>
std::string demangle(const char* name) {
int status;
char *realname;
std::string retValue;
realname = abi::__cxa_demangle(name, NULL, NULL, &status);
if (realname != NULL) {
retValue = std::string(realname);
free(realname);
}
return retValue;
}
template<class T>
std::string demangle() { return demangle(typeid(T).name()); }
a big thanks to soon who got me 98% of the way there.