Tl;dr: the most portable and least extensive way to get around that problem seems to be using the qualified name ::Derived
in your example:
template<typename T>
struct Derived : Base<T, Derived>
{
Derived(const T& _t) : Base<T, ::Derived>(_t) { }
};
Why?
The Problem is compiler non-conformance to C++11.
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-typespecifier of a friend class template declaration, it refers to the class template itself.
Thus your code should compile but unfortunately, all compilers I tested (clang 3.7, Visual Studio 2015 and g++5.3) refuse to do it.
Afaik, you should be able to denote the template in various ways, inside the Derived
definition:
- Using the injected name directly
Derived
- Qualified name of the class template
::Derived
- Using the injected class name, designating it as a template name
Derived<T>::template Derived
- Using a qualified name, again designating it as a template name
::template Derived
The compilation status of those compilers regarding those four options is as follows (using the anonymus namespace; where +
= successful compilation):
+------------------------------+----------+---------+-----------+
| Method | MSVS2015 | g++ 5.3 | clang 3.7 |
+------------------------------+----------+---------+-----------+
| Derived | - | - | - |
| ::Derived | + | + | + |
| Derived<T>::template Derived | - | - | + |
| ::template Derived | + | - | + |
+------------------------------+----------+---------+-----------+
When giving the namespace the name X
, the picture changes a little (namely g++
now accepts X::template Derived
whereas it rejected ::template Derived
):
+---------------------------------+----------+---------+-----------+
| Method | MSVS2015 | g++ 5.3 | clang 3.7 |
+---------------------------------+----------+---------+-----------+
| Derived | - | - | - |
| X::Derived | + | + | + |
| X::Derived<T>::template Derived | - | - | + |
| X::template Derived | + | + | + |
+---------------------------------+----------+---------+-----------+