Is class template instantiated when passed by reference?

207 Views Asked by At

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

1

There are 1 best solutions below

0
On

[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:

class A;
void foo(const A& a);

const A& get();

int main () 
{
  const A& a = get();
  foo(a);
  return 0;
}

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.