Stroustrup provides a Can_copy template. How does it work?
template struct Can_copy {
static void constraints(T1 a, T2 b) { T2
C++03 §14.7.1p1:
Unless a class template specialization has been explicitly instantiated (14.7.2) or explicitly specialized (14.7.3), 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. The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions or default arguments, of the class member functions, member classes, static data members and member templates; …
Thus, this code cannot instantiate Can_copy::constraints:
template
struct Can_copy {
static void constraints(T1 a, T2 b) { T2 c = a; b = a; }
Can_copy() { /* note the change here */ }
};
template
void draw_all(Container& c) {
typedef typename Container::value_type T;
Can_copy(); // accept containers of only Shape*s
}
But, in the original code, when Can_copy's ctor is instantiated, as it must be when it is used, its body (definition) is as well, and that triggers instantiation of Can_copy::constraints.
You can see this same problem in reverse, where an explicit instantiation gives you everything, even something you don't want:
typedef std::list::iterator Iter;
std::reverse_iterator x; // Implicit instantiation; works.
template std::reverse_iterator;
// Explicit instantiation; fails to instantiate op+ and other operators used
// for random access iterators from reverse_iterator.