template argument '(type)0' does not match 'EnumValue'

Viewed 98

Given this C++11 code:

#include <type_traits>

enum Enum { EnumValue };

template <typename>
struct Pred { constexpr static bool const value = true; };

template <
        typename T,
        typename ::std::enable_if<
            Pred<T>::value,
            Enum
        >::type = EnumValue>
class Huh {};

template <typename T>
constexpr bool f(Huh<T> const &) noexcept { return true; }

static_assert(f(Huh<int>()), "");

I get the following error message from GCC 7.3.0:

test.cpp:19:27: error: no matching function for call to 'f(Huh<int>)'
 static_assert(f(Huh<int>()), "");
                           ^
test.cpp:17:16: note: candidate: template<class T> constexpr bool f(const Huh<T>&)
 constexpr bool f(Huh<T> const &) noexcept { return true; }
                ^
test.cpp:17:16: note:   template argument deduction/substitution failed:
test.cpp:19:27: note:   template argument '(type)0' does not match 'EnumValue'
 static_assert(f(Huh<int>()), "");
                           ^

If I use int and 0 instead of Enum and EnumValue, the error is gone. Why does this fail with an enum?

1 Answers

Does anyone have any idea about how to work around this on broken versions of GCC while keeping the enum?

You can grit your teeth and tell the compiler what it fails to deduce:

static_assert(f<int>(Huh<int>()), "");

Success

If the unsightliness would be widespread maybe you can localize it in some conditionally compiled wrapping.

Related