Следующие классы реализуют CRTP. Я хотел бы, чтобы класс Derived использовал конструктор, предоставленный Base, поэтому я пишу using. Однако я получаю сообщение об ошибке «может наследовать конструктор только из прямой базы». То же самое для переменной-члена x.
template<template<typename, size_t> typename G, typename F, size_t U>
struct Base
{
double x;
Base(double x) : x{ x } {}
double gimme_x()
{
return (*static_cast<G<F, U>*>(this)).gimme_x();
}
};
template<typename F, size_t U>
struct Derived : Base<Derived, double, U>
{
using Base<Derived, double, U>::Base;
using Base<Derived, double, U>::x;
double gimme_x()
{
return x + 1.8;
}
};
Эту проблему можно смягчить, изменив реализацию шаблона-шаблона Base, чтобы просто использовать обычный шаблон.
template<typename G, typename F, size_t U>
struct Base
{
double x;
Base(double x) : x{ x } {}
double gimme_x()
{
return (*static_cast<G*>(this)).gimme_x();
}
};
template<typename F, size_t U>
struct Derived : Base<Derived<F, U>, double, U>
{
using Base<Derived<F, U>, double, U>::Base;
using Base<Derived<F, U>, double, U>::x;
double gimme_x()
{
return x + 1.8;
}
};
Хотя второй выглядит немного более подробным, похоже, что в данном случае он должен быть эквивалентен первому. В чем разница и почему реализация первого терпит неудачу?





Чтобы избежать внедренное имя класса, проще использовать полное имя ::Derived.
template<typename F, size_t U>
struct Derived : Base<Derived, double, U>
{
using Base<::Derived, double, U>::Base;
using Base<::Derived, double, U>::x;
double gimme_x()
{
return x + 1.8;
}
};
Код правильно компилируется как с gcc/clang Демо.
Это ошибка msvc, так как
In the following cases, the injected-class-name is treated as a template-name of the class template itself:
- it is followed by <
- it is used as a template argument that corresponds to a template template parameter
- it is the final identifier in the elaborated class specifier of a friend class template declaration.
Исходный код не будет компилироваться в Visual C++, но обходной путь решает эту проблему.