This code works fine:
#include <type_traits>
using namespace std;
enum class Type : char { Void };
struct FieldA { static constexpr Type type = Type::Void; };
template<typename Field> struct Signal {};
template<typename Field> struct SignalA : public Signal<Field> {};
struct SignalB : public Signal<void> {};
struct DerivedB : public SignalB {};
template<typename Signal, typename = void> struct Apply;
template<typename Field>
struct Apply<SignalA<Field>, typename std::enable_if<Field::type == Type::Void>::type> {};
template<typename Signal_t>
struct Apply<Signal_t, typename enable_if<is_base_of<SignalB, Signal_t>::value>::type>
{};
int main ()
{ Apply<SignalA<FieldA> > a; }
But what I want is improve readability erasing the long enable_if
s, so, let's attack, for example, the second enable_if
with an auxiliary class:
template<typename Signal>
struct IsBaseOfB
{ using type = typename enable_if<is_base_of<SignalB, Signal>::type; };
And change the second Apply
partial specialization with it:
template<typename Signal_t>
struct Apply<Signal_t, typename IsBaseOfB<Signal_t>::type>
{};
Even when the only possible specialization is the first one, gcc
throws me the following error:
main.cpp: In instantiation of 'struct IsBaseOfB<SignalA<FieldA> >':
main.cpp:21:78: error: no type named 'type' in 'struct std::enable_if<false, void>'
{ using type = typename enable_if<is_base_of<SignalB, Signal_t>::value>::type; };
Which is obvious since the enable_if
condition doesn't fit for SignalA<FieldA>
.
Which I don't understand is why that specialization failure is not ignored to get the first specialization (which I know it works).