Consider this example:
class A
{
void foo();
public:
void bar();
};
template <class> class B
{
B()
{
A a;
a.foo(); // 1
A::bar(); // 2
a.bar(1); // 3
}
};
Note B
is never instantiated.
clang++
reports all three marked lines as erroneous. g++
(4.8.3) accepts lines 1
and 2
and only reports line 3
.
If B
is instantiated, g++
happily reports all three lines as erroneous.
Is this a g++
bug? One would think so. A
is not a dependent name and its members should be checked normally at template definition time. Are there nuances I don't see?
It's not possible in general to tell whether
a.foo();
orA::bar();
are an error at template definition time, even for those specific definitions ofA::foo
andA::bar
.Generally speaking,
a.foo();
could be valid ifA
had some specialisations ofB<T>
as a friend, but not others, which would make the validity dependent on the template argument.Generally speaking,
A::bar();
could be valid ifB<T>
hadA
as a base class, directly or indirectly, and template classes do not generally know their base class yet at template definition time.Even though it's possible to detect that neither of these is possible here (
A
has no friends, andB<T>
has no base), it requires significant effort for little benefit. Because of this, it makes sense to simply always perform such checks at instantiation time, and that's the approach GCC has taken.There is actually no rule in C++ that requires this to be diagnosed at template definition time (as Marco A.'s answer rightly points out). It's only when a template is instantiated that any errors in the template definition render the program ill-formed with a requirement for a diagnostic, per 2.2p1 bullet point 8:
In your program, there is no instantiation, so there is no instantiation that fails.
Those pre-instantiation messages aren't enforced by the standard and are up to the compiler
n3337 § 14.6 - 8
emphasis mine