The following program compiles (see on godbolt), but it would not compile if we uncommented the definition of Buffer
.
template <int size>
struct Buffer /*{ char buf[size]; }*/;
template <class T>
struct Wrapper { void operator+() {} };
Wrapper<Buffer<-5>> a;
void f() { +a; }
The reason, the uncommented version does not compile: +a
triggers ADL, and to collect all candidates for operator+
, all associated classes must be checked for friend
functions. Buffer<-5>
is an associated class, so it must be instantiated. Instantiation fails, hence the compilation error. See this question.
I wonder if Buffer<-5>
must be instantiated, why don't we have a compilation error, if Buffer
is not defined?
You can (implicitly) instantiate a class template from only a declaration; you get an incomplete class type, just like from struct A;
([temp.inst]/2). It’s not an error, of course, to do ADL with an incomplete associated class; the class in question is simply not searched for friend declarations.