jeudi 22 janvier 2015

Counting the total number of types in a nested pack

NumTypes<Args...>::value is to give the total number of types among in a nested pack, e.g. if



using T = Group<int, bool, Wrap<char, Pack<char, long, Group<char, Object, short>, short>, double>, long>;


then NumTypes<T>::value will be 11 (we do not count the wrapper classes themselves). The following code works correctly, but when I replace any of the types with std::string I get a flurry of std::allocator errors that never terminates (with GCC 4.8.1). I suspect other types will generate the same error. Why? And how to fix the code to avoid this weird error?



#include <iostream>
#include <string>

#define show(variable) std::cout << #variable << " = " << variable << std::endl;

template <typename T>
struct IsPack {
static const bool value = false;
};

template <template <typename...> class P, typename... Args>
struct IsPack<P<Args...>> {
static const bool value = true;
};

template <typename...> struct NumTypes;

template <typename T>
struct NumTypes<T> {
static const int value = 1;
};

template <template <typename...> class P>
struct NumTypes<P<>> { static const int value = 0; };

template <template <typename...> class P, typename First, typename... Rest>
struct NumTypes<P<First, Rest...>> {
static const int numInFirst = IsPack<First>::value ? NumTypes<First>::value : 1;
static const int value = numInFirst + NumTypes<P<Rest...>>::value;
};

template <typename...> struct Pack;
template <typename...> struct Group;
template <typename...> struct Wrap;
struct Object {};

int main() {
using A = Pack<int, Object, long>;
show (NumTypes<A>::value) // 3

using B = Pack<int, bool, Pack<char, double>, long>;
show (NumTypes<B>::value) // 5

using C = Group<int, bool, Wrap<char, Pack<char, long, Group<char, Object, short>, short>, double>, long>;
show (NumTypes<C>::value) // 11

using D = Group<Pack<int, Object, double>, bool, Wrap<char, Pack<char, double, Group<char, Pack<char, long, short>, int, Object>, short>, double>, long>;
show (NumTypes<D>::value) // 16
}

Aucun commentaire:

Enregistrer un commentaire