Note: An injected-class-name is just the identifier used to declare the class (as opposed to other names which also refer to the same class, such as typedef names).
Here's the relevant quote from the C++11 Standard, section 14.6.1p1:
Like normal (non-template) classes, class templates have an injected-class-name (Clause 9). The injected-class-name can be used as a template-name or a type-name. When it is used with a template-argument-list, as a template-argument for a template template-parameter, or as the final identifier in the elaborated-type-specifier of a friend class template declaration, it refers to the class template itself. Otherwise, it is equivalent to the template-name followed by the template-parameters of the class template enclosed in
<>
.
So clearly this is legal in C++11.
However, the book correctly describes the behavior of C++03:
Like normal (non-template) classes, class templates have an injected-class-name (clause 9). The injected-class-name can be used with or without a template-argument-list. When it is used without a template-argument-list, it is equivalent to the injected-class-name followed by the template-parameters of the class template enclosed in
<>
. When it is used with a template-argument-list, it refers to the specified class template specialization, which could be the current specialization or another specialization.
Aside from reversing the logic, we see that C++03 contained one case where the identifier referred to the template (when template arguments were provided) and C++11 adds two additional cases, one of which affects this code.
So in C++03, the code was equivalent to X<C<T>> c;
, which is an error because X
needs to be passed a template and not a type.
Bottom line: For learning about the language, templates especially, you need a book on C++11. Older books remain useful with respect to architecture and high level design, but can't explain language intricacies which changed after they were published.