I would like to be able to check invariants for classes that are used in metaprograms. My first naive approach was
template <int N>
struct digit
{
static_assert((N >= 0) && (N < 10), "bad invariant");
};
using boom = digit<99>;
However, this compiles without any problems. A static statement is only triggered when an illegal class is created.
This is possible by adding an additional template parameter:
#include <type_traits>
template <int N,
typename = typename std::enable_if<(N >= 0) && (N < 10)>::type>
struct digit;
using crash = digit<-7>;
When I wanted to apply this technique to a class that is used as a list of types:
#include <type_traits>
template <typename ...> struct are_integral;
template <typename T, typename ...Ts>
struct are_integral<T, Ts...>
{
static const bool value = std::is_integral<T>::value &&
are_integral<Ts...>::value;
};
template <>
struct are_integral<> : std::true_type { };
template <typename ...Ts,
typename = typename std::enable_if<are_integral<Ts...>::value>::type>
struct list;
using ok = list<int, long, char>;
using bad = list<double>;
It just doesn't work, since gcc complains that
error: parameter package "Ts" should be at the end of the template a list of structural parameter lists;
Even if this works, the class is useless since the template parameter package does not reflect the list of types.
So, I tried to use the “illegal” base class:
template <typename> struct check;
template <typename ...Ts>
struct list : check<typename std::enable_if<are_integral<Ts...>::value>::type>
{ };
using ok = list<int, long, char>;
using bad = list<double>;
This compiles without a problem.
- ++ 11 ?