I recently started to learn modern template metaprogramming and I wrote myself an index_of function for types.
template<std::size_t Index, class C, class A> struct mp_index_of_impl{};
template<std::size_t Index, class C,template<class...> class A,class ...Ts>
struct mp_index_of_impl<Index,C,A<C,Ts...>>{
using type = std::integral_constant<std::size_t,Index>;
};
template<std::size_t Index, class C,template<class...> class A,class ...Ts,class T1>
struct mp_index_of_impl<Index,C,A<T1,Ts...>>{
using type = typename mp_index_of_impl<Index + 1,C,A<Ts...>>::type;
};
template<std::size_t Index, class C,template<class...> class A> struct mp_index_of_impl<Index,C,A<>>{
//static_assert(false,"Does not contain type");
using type = std::integral_constant<std::size_t,0>;
};
The problem is my last specialization
template<std::size_t Index, class C,template<class...> class A>
struct mp_index_of_impl<Index,C,A<>>{
//throw a compile error here
};
I tried to use static_assert like this
template<std::size_t Index, class C,template<class...> class A> struct mp_index_of_impl<Index,C,A<>>{
static_assert(false,"Does not contain type");
};
But this will throw a compile error every time, even if it is not matched.
I want to throw a compile error with a custom error message if this template specialization is matched. How would I do this?
If you put a
static_assert(false,...)
in a template specialization then it is always impossible to generate valid code from it. This is ill-formed, no diagnostic required.A workaround to this is to make your
static_assert
depend on the template parameter:To get a truly well-formed solution here is a little annoying. You're running into [temp.res]/8:
So what we need to do is avoid anything that could do
static_assert(false, ...)
. In this case, we have a partial opening. We could specialize on the case where we only have one type left and assert that this is what we're looking for:This would not handle the case of empty lists, but for that at top level you can add another
static_assert
for non-emptiness:Although, in practice, TartanLlama's solution will probably get you by every compiler, and I would probably just use it.