хороший вопрос;это заставило меня узнать что-то новое о static_cast
.
. Я думаю, что следующий код достигает того, что вы хотите: предоставляет базовый класс для CRTP с функцией-членом, которая преобразует this
в тип Derived, но толькоделает его доступным для прямых потомков этого базового класса.Он компилируется с GCC 4.3.4 ( проверено на ideone ) и Clang (протестировано на llvm.org).Извините, я не смог устоять перед изменением имен, которые меня смущают.
#include <iostream>
template<class Derived>
class CRTP {
protected:
Derived * derived_this() {
return static_cast<Derived *>(this);
}
};
template<class Derived>
struct Parent : public CRTP<Derived> {
private:
using CRTP<Derived>::derived_this;
public:
int y() {
return derived_this()->x();
}
};
struct Child : public Parent<Child> {
int x() {
return 5;
}
int z() {
return y();
}
};
int main() {
std::cout << Child().z() << std::endl;
return 0;
}
Этот вариант работает, потому что наследование является публичным, что позволяет стандартное преобразование указателя на производный класс вуказатель на базовый класс, а также обратное преобразование (из базового в производное) с static_cast
, в котором нуждается CRTP.Частное наследство в вашем коде запрещено.Поэтому я сделал публичное наследование, изменил защищаемый метод и в Parent
дополнительно ограничил доступ, поместив объявление using
в приватный раздел.