4

I have this code:

template <typename A>
class templatedclass {
    public:
    using type = templatedclass;
};

template <typename A>
class sinkstuff {
    public:
    void print() {
        cout << "generic sinkstuff";
    }
};
template <typename A>
class sinkstuff <templatedclass<A>> {
    public:
    void print() {
        cout << "partiallyspecialized sinkstuff";
    }
};

template <typename NtoA>
struct pass_parameter : sinkstuff<typename templatedclass<NtoA>::type> {}; 


int main() {
  pass_parameter<int> obj;
  obj.print();
  cout << is_same<templatedclass<int>, typename templatedclass<int>::type>::value; // 1, yes
}

I always thought the "using directive" was a typedef on steroids. How come I can use "templatedclass<int>::type" without specifying the parameter again, i.e. "templatedclass<int>::type<int>" ?

Isn't "using type = templatedclass" just a textual substitution? Am I missing something?

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Dean
  • 6,610
  • 6
  • 40
  • 90

2 Answers2

4

The name of a class is "injected" into the class, this is called the injected-class-name. It is similar to:

class my_class_name
{
public:
    typedef ::my_class_name my_class_name;
};

(But this of course doesn't compile, a class may not have a manually declared member of the same name as the class.)

Class templates also have an injected-class-name, and it can be used to refer to the class template itself, or the current specialization (including the current template arguments), depending on the context:

[temp.local]/1

Like normal (non-template) classes, class templates have an injected-class-name. 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 <>.

dyp
  • 38,334
  • 13
  • 112
  • 177
2

This doesn't have anything to do with the using directive. Within the definition of A<T> (and the using directive is in that scope), saying A is the same as saying A<T>.

It's the same reason you may write:

template <typename T>
struct A
{
   void foo(const A&);
};

instead of

template <typename T>
struct A
{
   void foo(const A<T>&);
};

For more information, search for "injected-class-name".

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055