У меня есть код, который использует этот дизайн, упрощенный, чтобы получить этот MCVE - код и ошибки компилятора следуют.
Основная проблема заключается в том, что я думал, что поддержка класса CRTP предоставит шаблонному базовому классу доступ к закрытым членам производного класса CRTP, включая его частный конструктор.
Но, видимо, это не так. Почему?
этот код на wandbox :
#include <iostream>
using namespace std;
template <class CRTP>
class Base
{
friend CRTP;
public:
static void Factory()
{
cout << "Base::Factory()" << endl;
CRTP x;
x.Hello();
}
virtual void Hello() { cout << "Base::Hello()" << endl; }
protected:
Base() { cout << "Base::Base()" << endl; }
virtual ~Base() { cout << "Base::~Base()" << endl; }
};
class Derived final : public Base<Derived>
{
public:
void Hello() override;
private:
Derived() { cout << "Derived::Derived()" << endl; }
~Derived() override { cout << "Derived::~Derived()" << endl; }
};
int main()
{
Derived::Factory();
// Expected output:
// Base::Factory()
// Base::Base()
// Derived::Derived()
// Derived::Hello()
// Derived::~Derived()
// Base::~Base()
}
И получение этой ошибки компилятора (из clang 9.0.0, но gcc жалуется так же):
prog.cc:12:12: error: calling a private constructor of class 'Derived'
CRTP x;
^
prog.cc:33:14: note: in instantiation of member function 'Base<Derived>::Factory' requested here
Derived::Factory();
^
prog.cc:27:3: note: declared private here
Derived() { cout << "Derived::Derived()" << endl; }
^
prog.cc:12:12: error: variable of type 'Derived' has private destructor
CRTP x;
^
prog.cc:28:11: note: declared private here
virtual ~Derived() { cout << "Derived::~Derived()" << endl; }
^
2 errors generated.
(К сведению: вариант использования: я хочу, чтобы базовый класс шаблона управлял временем жизни (включая конструкцию) экземпляров производного класса (CRTP) через статическую фабрику. Поэтому я хочу, чтобы производные классы объявляли свои конструкторы частными, но доступными для метод родительской статической фабрики. В этом примере показан экземпляр производного класса, созданный в стеке, но возникают те же ошибки, если он создается в куче (и возвращается).)