I have the following code:
template <typename TC>
class C
{
struct S
{
template <typename TS>
void fun() const
{}
};
void f(const S& s)
{
s.fun<int>();
}
};
// Dummy main function
int main()
{
return 0;
}
When building this with both gcc 9.2 and clang (9.0), I'm getting a compilation error due to the template
keyword being required for invoking fun
. Clang shows:
error: use 'template' keyword to treat 'fun' as a dependent template name
s.fun<int>();
^
template
I don't understand why the compiler thinks fun
is a dependent name in the context of f
, since f
is not a template itself. If I change C
to be a regular class instead of a template, the error goes away; however, I don't see why there should be an error in the first place since neither S
nor f
depend on TC
.
Oddly enough, MSVC 19.22 compiles this just fine.
Before voting to close as dupe of Where and why do I have to put the "template" and "typename" keywords? please consider this is a special case where even if S
is indeed a dependent name, in the context of f
it would not be dependent if not for the fact that they are members of the current instantiation.
template<typename T>
struct C
{
struct S
{
int a = 99;
};
void f(S s, int i)
{
s.a<0>(i);
}
};
template<>
struct C<long>::S
{
template<int>
void a(int)
{}
};
int main()
{
C<int>{}.f({}, 0); // #1
C<long>{}.f({}, 0); // #2
}
s.a<0>(i)
is parsed as an expression containing of two comparison operations <
and >
, and this is fine for #1 but fails for #2.
If this is changed to s.template a<0>(i)
then #2 is OK and #1 fails. Thus the template
keyword is never redundant here.
MSVC is capable of interpreting the expression s.a<0>(i)
both ways within the same program. But this is not correct according to the Standard; each expression should have only one parse for the compiler to deal with.