Interestingly, the GCC in this example is even contradictory.
Lets you declare an incomplete template class that you must provide, these are some good compiler messages we can abuse:
template <typename T> struct type_check;
We will also create another const char* that we can use for testing:
constexpr char NOT_FOO[]{"NOT_FOO"};
Now we will see that the compiler is suffocating:
template <const char *NAME> void foo() { type_check<decltype(Value<FOO>)> a; type_check<decltype(Value<NAME>)> b; type_check<decltype(Value<NOT_FOO>)> c; type_check<decltype(Value<FOO>.foo())> d; type_check<decltype(Value<NAME>.foo())> e; type_check<decltype(Value<NOT_FOO>.foo())> f; }
Here are the errors that GCC 5.1.0 produces (edited bit for clarity):
test.cpp:21:38: error: 'type_check<Foo> a' has incomplete type type_check<decltype(Value<FOO>)> a; ^ test.cpp:22:39: error: 'type_check<Foo> b' has incomplete type type_check<decltype(Value<NAME>)> b; test.cpp:25:42: error: 'type_check<char [8]> c' has incomplete type type_check<decltype(Value<NOT_FOO>)> c; ^ test.cpp:23:44: error: 'type_check<void> c' has incomplete type type_check<decltype(Value<FOO>.foo())> c; test.cpp:24:37: error: request for member 'foo' in 'Value<NAME>', which is of non-class type 'char [8]' type_check<decltype(Value<NAME>.foo())> d; test.cpp:28:40: error: request for member 'foo' in 'Value<((const char*)(& NOT_FOO))>', which is of non-class type 'char [8]' type_check<decltype(Value<NOT_FOO>.foo())> f;
Let them take this data at a time.
Error 1:
test.cpp:21:38: error: 'type_check<Foo> a' has incomplete type type_check<decltype(Value<FOO>)> a;
In the first error, we see that GCC correctly infers that the type Value<FOO> is equal to Foo . This is what we expect.
Error 2:
test.cpp:22:39: error: 'type_check<Foo> b' has incomplete type type_check<decltype(Value<NAME>)> b;
Here GCC does the forwarding correctly and it works that Value<NAME> is of type Foo .
Error 3:
test.cpp:25:42: error: 'type_check<char [8]> c' has incomplete type type_check<decltype(Value<NOT_FOO>)> c;
Great, Value<NOT_FOO> is "UNKNOWN" , so this is correct.
Error 4:
test.cpp:23:44: error: 'type_check<void> c' has incomplete type type_check<decltype(Value<FOO>.foo())> c;
This is normal, Value<FOO> is Foo , which can be called Foo on, returning void .
Error 5:
test.cpp:24:37: error: request for member 'foo' in 'Value<NAME>', which is of non-class type 'char [8]' type_check<decltype(Value<NAME>.foo())> d;
It is odd. Although with error 2, we see that GCC knows that the type Value<NAME> is Foo , when it tries to search for the function Foo , it is mistaken and uses the primary template instead. This may be some mistake in finding a function that incorrectly solves the arguments of a non-piggy type template.
Error 6:
test.cpp:28:40: error: request for member 'foo' in 'Value<((const char*)(& NOT_FOO))>', which is of non-class type 'char [8]' type_check<decltype(Value<NOT_FOO>.foo())> f;
Here we see that the compiler correctly selects the main template when developing Value<NOT_FOO> . I'm interested in (const char*)(& NOT_FOO)) , which GCC outputs as type NOT_FOO . Maybe this is a pointer to this problem? I'm not sure.
I would suggest making a mistake and pointing out a discrepancy. This may not fully answer your question, but I hope this helps.