This seems to be another "who's doing it well?" question since gcc 6.0.0 and clang 3.7.0 behaves different.
Let's suppose we have a variable template which takes a const char *
as non template argument and is specialized for a given pointer:
constexpr char INSTANCE_NAME[]{"FOO"};
struct Struct{ void function() const { std::cout << __PRETTY_FUNCTION__; } };
std::ostream &operator <<(std::ostream &o, const Struct &) { return o << INSTANCE_NAME; }
template <const char *> char Value[]{"UNKNOWN"};
// spezialization when the pointer is INSTANCE_NAME
template < > Struct Value<INSTANCE_NAME>{};
Note that the template variable have different types depending on the specialization. Ten we have two template functions, each of one takes a const char *
as non template argument and forwards it to the variable template:
template <const char *NAME> void print()
{
std::cout << Value<NAME> << '\n';
}
template <const char *NAME> void call_function()
{
Value<NAME>.function();
}
Then, calling this functions results in different behaviours:
int main()
{
print<INSTANCE_NAME>();
call_function<INSTANCE_NAME>();
return 0;
}
clang 3.7.0 prints FOO
and void Struct::function() const
(as I was expecting) while gcc 6.0.0 fails to compile with the error below:
request for member 'function' in 'Value', which is of non-class type 'char [8]'
I'm almost sure that gcc failed to forward the template non-type argument NAME
to the variable template Value
in the function call_function
and for this reason it selects the unspecialized variable template which is the one with 'char [8]'
type...
It is acting like it is copying the template argument. This only happens when calling a member function of the object, if we comment the body of call_function
, the output is FOO
not UNKNOWN
, so in the print
function the forwarding is working even in gcc.
So
- What's the correct behaviour? (mi bet is for clang)
- How can I open a bug ticket for the compiler who's doing it wrong?