Consider the following example:
template <typename T>
class A
{
public:
void foo () const {t->foo();}
virtual void fooVirtual() {t->foo();} // MSVC: use of undefined type 'B'
protected:
T* t;
};
class B; // only forward declared
const A<B>& get(); // will be defined in another translation unit
void foo(const A<B>& a); // will be defined in another translation unit
int main ()
{
const A<B>& a = get();
foo(a); // MSVC: class template instantiation 'A<B>' being compiled
return 0;
}
This compiles in CLang and GCC, but generates the error messages as mentioned above by MSVC. Which compiler behaviour is C++ compliant?
Should a class template specialization (A<B>
) be instantiated when passed by reference?
See example at Compiler Explorer
[temp.inst] "...the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined object type or when the completeness of the class type affects the semantics of the program."
I don't see it being the case here. Let's replace the specialization with an incomplete type:
This compiles just fine (demo), so no complete type is required at this point. Adding a pair of curly braces after
class A
changes nothing. So MSVC is probably wrong.