CWG Issue 1004 (original) (raw)

This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 118e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2025-11-05


1004. Injected-class-names as arguments for template template parameters

Section: 13.8.2 [temp.local]Status: C++11Submitter: Jason MerrillDate: 2009-11-19

[Voted into the WP at the March, 2011 meeting as part of paper N3262.]

The injected-class-name of a class template can be used either by itself, in which case it is a type denoting the current instantiation, or followed by a template argument list, in which case it is a_template-name_. It would be helpful to extend this treatment so that the injected-class-name could be used as an argument for a template template parameter:

template <class T> struct A { };

template <template <class> class TTP> struct B { };

struct C: A<int> {
   B<A> b;
};

(This is accepted by g++.)

James Widman:

It would not be so helpful when used with overloaded function templates, for example:

template <template <class> class TTP>  void f(); // #1
template <                 class T  >  void f(); // #2

template <class T> struct A { };

struct C: A<int> {
    void h(  ) {
        f<A>(); //  #1?  #2?  Substitution failure?
    }
};

(See also issue 602.)

Proposed resolution (November, 2010) [SUPERSEDED]:

Change 13.8.2 [temp.local] paragraphs 1-5 as follows:

Like normal (non-template) classes, class templates have an injected-class-name (Clause 11 [class]). The injected-class-name can be used with or without a_template-argument-list_ as a template-name_or a type-name. ~~When it is used without a_template-argument-list, it is equivalent to the injected-class-name followed by the template-parameter_s of the class template enclosed in <>.~~ 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 specified class template specialization, which could be the current specialization or another specialization. class template itself. Otherwise, it is equivalent to the _template-name_followed by the _template-parameter_s of the class template enclosed in <>.

Within the scope of a class template specialization or partial specialization, when the injected-class-name is not followed by a< used as a _type-name_, it is equivalent to the injected-class-name _template-name_ followed by the_template-argument_s of the class template specialization or partial specialization enclosed in<>. [Example:

template<template class T> class A { }; template class Y; template<> class Y { Y* p; // meaning Y Y* q; // meaning Y A* a; // meaning A<::Y> class B { template friend class Y; // meaning ::Y }; };

—_end example_]

The injected-class-name of a class template or class template specialization can be used either with or without a_template-argument-list_ as a template-name or a type-name wherever it is in scope. [Example:

template struct Base { Base* p; };

template struct Derived: public Base { typename Derived::Base* p; // meaning Derived::Base };

template<class T, template class U = T::template Base> struct Third { }; Third<Base> t; // OK, default argument uses injected-class-name as a template

—_end example_]

A lookup that finds an injected-class-name (6.5.2 [class.member.lookup]) can result in an ambiguity in certain cases (for example, if it is found in more than one base class). If all of the injected-class-names that are found refer to specializations of the same class template, and if the name is followed by a_template-argument-list_ used as a_template-name_, the reference refers to the class template itself and not a specialization thereof, and is not ambiguous. [Example:

template struct Base { }; template struct Derived: Base, Base { typename Derived::Base b; // error: ambiguous typename Derived::Base d; // OK };

—_end example_]

When the normal name of the template (i.e., the name from the enclosing scope, not the injected-class-name) is used without a_template-argument-list_, it always refers to the class template itself and not a specialization of the template. [Example:...

This resolution also resolves issue 602.