2016-01-21 2 views
1

Надеюсь, что это не дублируется, но не удалось найти элегантное решение. Можно ли сказать, что подклассы специального базового класса могут создаваться только в фабричной функции шаблона? Из-за простоты я только хочу заставить это поведение в базовом классе. Вот простой пример:Проверьте, открыты ли конструкторы подкласса в C++

template <class T> 
T* createBase(); 

template<typename T> 
class Base { 
protected: 
    template <class T> 
    friend T* createBase(); 

    static T* create() 
    { 
     return new T(); 
    } 
}; 

class TestClass1 : public Base<TestClass1> 
{ 
public: 
    TestClass1() : Base() {} 
}; 

template <class T> 
T* createBase() 
{ 
    static_assert(std::is_base_of<Base<T>, T>::value, "use the createBase function only for Base<T> subclasses"); 
    return Base<T>::create(); 
} 

На самом деле это разрешено:

TestClass2 *testClass = createBase<TestClass2>(); 
TestClass2 tester; 

Но я только хочу, чтобы это:

TestClass1 *testClass = createBase<TestClass1>(); //allowed 
TestClass1 tester; // compile error 

Конечно, я знаю, что я только должен поставить конструктор TestClass1 private или protected. Но было бы очень приятно сказать, что в объекте Base.

Edit:

ошибка компиляции, когда конструктор подкласса является публичным будет также хорошим решением. Может быть, с static_assert().

+0

Несомненно, я могу это сделать, но я наблюдаю за тем, чтобы заставить это поведение в классе . Пользователь не должен создавать объект типа Base без заводского метода. Итак, как я могу заставить пользователя установить конструктор как закрытый, так и защищенный. – PeterNL

ответ

1

Вы не можете контролировать доступность конструктора из базового класса, даже с помощью CRTP.

Что вы можете сделать, это добавить static_assert в базовой CTOR проверки, что T ака производного класса не имеет общедоступный CTOR по умолчанию:

template <class T> 
class Base { 
public: 
    Base() { 
     static_assert(!std::is_default_constructible<T>::value, 
         "T must not be default constructible"); 
    } 
}; 

static_asswert не работает в области видимости класса по причинам showned здесь: CRTP std::is_default_constructible not working as expected

+0

idk, я полностью отсталый, не могу заставить 'static_assert' работать. Я вернусь после того, как уберу голову. – bolov

+0

Как [это] (http://coliru.stacked-crooked.com/a/9f2d664520cb1fa0)? Я предполагаю, что вы попробовали 'static_assert' только в области класса, которая не работает по причинам, которые я не совсем уверен. Возможно, связано с декларацией 'friend'. – TartanLlama

+0

@TartanLlama Я пробовал в ctor, как и вы, после того, как он не работал на уровне класса. Смущенный, потому что я сохранил старый код, похоже, что это не сработало. – bolov

Смежные вопросы