Here's a simple template;
template <class T>
class tt {
private:
T x;
public:
tt() {x=0;};
Add(T p) {x += p;};
};
... and then a subclass of it;
class cc : public tt<int> {
public:
cc() : tt() {};
};
This compiles fine in VC, but not in C++ Builder (XE) where it gives a E2102 error. The C++ Builder compiler needs the following syntax on the constructor of the cc class to compile;
cc() : tt<int>() {};
In fact, the C++ Builder compiler needs the template parameters repeated every time the tt template are mentioned within the cc class.
Does the standard C++ specification specify the need for constantly repeating the template parameters or is the C++ Builder compiler wrong?
C++ Builder is wrong here. The reason why you should be able to use the ancestor's name in the constructor's member initializer list has to do with the concept of injected class name.
When you define a class, the compiler inserts the name of the class into that class and makes it refer to itself. This injected name is what allows you to use the name of the class without template arguments inside the class.
template <class T>
struct tt {
// The compiler behaves as if there was the following.
// typedef tt<T> tt;
};
This injected name is what gets looked up when you use the name tt
in the member initializer list.
(For the record, clang accepts the snippet without the template argument.)
Bonus: had you defined cc
as a class template with the template parameter T
and the ancestor was dependent on T
, the name tt
would not be found in the context of cc
's constructor's member initializer list.
template <class T>
class cc : tt<T> {
cc()
: tt<T>() /* You must use <T> here. */
{
}
};
you can avoid the repetitions by using typedef:
typedef tt<int> tti;
...
class cc : public tti {
public:
cc() : tti() {};
};