In the code below function f()
can call the operator bool()
and operator *()
member functions of unique_ptr<C>
for the incomplete class C
. However when function g()
tries to call those same member functions for unique_ptr<X<C>>
, the compiler suddenly wants a complete type and tries to instantiate X<C>
, which then fails. For some reason unique_ptr<X<C>>::get()
does not cause template instantiation and compiles correctly as can be seen in function h()
. Why is that? What makes get()
different from operator bool()
and operator *()
?
#include <memory>
class C;
std::unique_ptr<C> pC;
C& f() {
if ( !pC ) throw 0; // OK, even though C is incomplete
return *pC; // OK, even though C is incomplete
}
template <class T>
class X
{
T t;
};
std::unique_ptr<X<C>> pX;
X<C>& g() {
if ( !pX ) throw 0; // Error: 'X<C>::t' uses undefined class 'C'
return *pX; // Error: 'X<C>::t' uses undefined class 'C'
}
X<C>& h() {
if ( !pX.get() ) throw 0; // OK
return *pX.get(); // OK
}
class C {};