Disclaimer
this is not an answer, but rather a long comment
My language-lawyer skills are too low to fully understand the standard but here are a few things I discovered from experimenting with the code. Everything that follows is based on my (far from perfect) understanding of the matter and probably needs some reviews.
Investigation
First off, I went to a fully defined standard version (C++17) so we operate on a well defined implementation.
Looking at this code it seems like MSVC still has some problems (with its lookup, I guess?) when it comes to template instantiation and redefinition. I wouldn't trust MSVC that much in our scenario.
That beeing said, lets think about why we could need the template keyword at
return yF.template head<1>();
Dependent names
Sometimes, inside templates, we have to help the compiler decide whether a name refers to
- a value
int T::x = 0,
- a type
struct T::x {};, or
- a template
template <typename U> T::foo<U>();
If we refer to a value, we do nothing. If we refer to a type, we have to use typename. And if we refer to a template we use template. More on that subject can be found here.
I don't understand the standard specification when it comes to the actual definition of a dependent name but here are some observations.
Observations
Lets take a look at the reference code
template <int N>
struct Matrix
{
template <int Idx>
int head() { return Idx; }
};
template <typename T>
struct Test
{
static constexpr int RayDim = 3;
int func() const
{
Matrix<RayDim> yF;
return yF.head<1>(); // clang complains, gcc and msvc are ok
}
};
struct Empty {};
int test()
{
Test<Empty> t;
return t.func();
}
Usually RayDim should be a dependent name (because it's inside the template Test) which would cause Matrix<RayDim> to be a dependent name aswell. For now, lets assume that Matrix<RayDim> actually is a dependent name. This makes Matrix<RayDim>::head a dependent name aswell. Since Matrix<RayDim>::head is a templated function it is a template in itself and the rules of dependent names from above apply, requiring us to use the template keyword. This is what clang is complaining about.
However, since RayDim is defined inside Test and func is also defined inside the same template and not a templated function in itself, I don't think RayDim actually is a dependent name in the context of func. Furthermore, RayDim doesn't rely on the template arguments of Test. In this case, Matrix<RayDim> and Matrix<RayDim>::head respectively, would become non-dependent names, which allows us to omit the template keyword. This is why gcc (and msvc) compile.
If we were to template RayDim aswell, like here
template <typename>
static constexpr int RayDim = 3;
gcc would treat it as a dependent name aswell (which is correct, since there might be a template specialization later so we don't know at that point). Meanwhile, msvc happily accepts everything we throw at it.
Conclusion
It seems like it's boiling down to whether RayDim is a dependent name in the context of Test<T>::func or not. Clang thinks it is, gcc doesn't. From some more test it looks like msvc sides with clang on this one. But it's also kinda doing it's own thing, so who knows?
I would side with gcc here as I see no possible way of RayDim becoming dependent at the point where func is instantiated.