Ответ 1
Tl; dr: самый портативный и наименее обширный способ обойти эту проблему, похоже, использует в вашем примере квалифицированное имя ::Derived
:
template<typename T>
struct Derived : Base<T, Derived>
{
Derived(const T& _t) : Base<T, ::Derived>(_t) { }
};
Почему?
Проблема заключается в несоответствии компилятора С++ 11.
Подобно обычным (не шаблонным) классам, шаблоны классов имеют имя с введенным классом (раздел 9). Введенное имя класса можно использовать в качестве имени шаблона или имени типа. Когда он используется с шаблоном-аргументом-списком, в качестве аргумента-шаблона для шаблона-шаблона шаблона или в качестве конечного идентификатора в специфицированном указателе типа объявление класса класса друга, относится к самому шаблону класса.
Таким образом, ваш код должен компилироваться, но, к сожалению, все компиляторы, которые я тестировал (clang 3.7, Visual Studio 2015 и g++ 5.3), отказываются это делать.
Afaik, вы должны иметь возможность обозначать шаблон различными способами внутри определения Derived
:
- Использование введенного имени напрямую
Derived
- Квалифицированное имя шаблона класса
::Derived
- Используя имя введенного класса, обозначив его как имя шаблона
Derived<T>::template Derived
- Используя квалифицированное имя, снова обозначив его как имя шаблона
::template Derived
Состояние компиляторов этих четырех параметров выглядит следующим образом (с использованием пространства имен anonymus, где +
= успешная компиляция):
+------------------------------+----------+---------+-----------+
| Method | MSVS2015 | g++ 5.3 | clang 3.7 |
+------------------------------+----------+---------+-----------+
| Derived | - | - | - |
| ::Derived | + | + | + |
| Derived<T>::template Derived | - | - | + |
| ::template Derived | + | - | + |
+------------------------------+----------+---------+-----------+
При присвоении пространству имен имя X
изображение немного меняется (а именно g++
теперь принимает X::template Derived
, тогда как оно отклонено ::template Derived
):
+---------------------------------+----------+---------+-----------+
| Method | MSVS2015 | g++ 5.3 | clang 3.7 |
+---------------------------------+----------+---------+-----------+
| Derived | - | - | - |
| X::Derived | + | + | + |
| X::Derived<T>::template Derived | - | - | + |
| X::template Derived | + | + | + |
+---------------------------------+----------+---------+-----------+