Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do members of a template class need to be parameterized by the parameters of their template class

Tags:

c++

templates

In page 668 of Stroustrup's book (4th edition - first printing) you`ll find the following example of a template class?

template<typename C>
class String{
public:
    String();
    ...
private:
    int sz;
    C* ptr;
};

In page 679 the author writes:

Members of a template class are themselves templates parameterized by the parameters of their template class. When such a member is defined outside its class, it must explicitly be declared as template. For example:

template<typename C>
String<C>::String()
    :sz(0), ptr(ch)
{
    ch[0] = {}; 
}

There is an obvious error in this example. The variable ch doesn't make any sense above. But that has nothing to do with my question. What I'd like to know is why the constructor above can't be defined without the parameter C, as shown below?

template<typename C>
String::String()
    : sz(0), ptr(nullptr)
{
}
like image 817
WaldB Avatar asked Jul 26 '18 12:07

WaldB


1 Answers

String is the name of a template, not a class. A template is not not even a type, so it doesn't have members. A template specialization is a class, however. You need to plug in C in order to specify which specialization it is you are referring to for the purposes of this definition.

Now it just so happens that the definition itself is a template, but that is because you are defining things for a family of specializations. Nevertheless the fact remains that you need to name those specializations explicitly.

Finally, the reason you only need to specify the specialization once is that the template name is treated in a special manner inside the scope of a class template specialization. Inside that scope the template name refers to the the injected class name, to the specialization itself. That's why

template<typename C>
String<C>::String<C>()
    :sz(0), ptr(ch)
{
}

... can be written as...

template<typename C>
String<C>::String()
    :sz(0), ptr(ch)
{
}

Since String<C> already established the specialization we are referring to, and we are inside its scope, we can use String with its special meaning as the injected class name.

like image 101
StoryTeller - Unslander Monica Avatar answered Nov 07 '22 21:11

StoryTeller - Unslander Monica