У меня есть решение для обеих версий, хотя оно немного сложнее.
#include <type_traits>
enum class Type { Car, Person, Truck };
template<Type TYPE>
struct ObjectConfig;
template<>
struct ObjectConfig<Type::Car>
{ };
template<>
struct ObjectConfig<Type::Person>
{ };
template<Type T>
struct FakeDependency: public std::false_type
{ };
template<Type TYPE, Type DELEGATED_TYPE = TYPE, typename DUMMY = typename std::enable_if<DELEGATED_TYPE == TYPE>::type >
struct Object;
template<Type TYPE, Type DELEGATED_TYPE, typename DUMMY>
struct Object
{
static_assert( FakeDependency<DELEGATED_TYPE>::value, "Not supported!" );
};
template<Type DELEGATED_TYPE, typename DUMMY>
struct Object<Type::Car, DELEGATED_TYPE, DUMMY>
{
ObjectConfig<DELEGATED_TYPE> m_params;
};
template<Type DELEGATED_TYPE, typename DUMMY>
struct Object<Type::Person, DELEGATED_TYPE, DUMMY> : public ObjectConfig<DELEGATED_TYPE>
{ };
int main() {
Object<Type::Car> c;
Object<Type::Person> p;
//Object<Type::Truck> t; // Static assertion
//Object<Type::Car, Type::Person> cp; // template 3 (enable_if) invalid
}
Вы можете проверить полный код
Я ввел шаблон, который скрывает первый, имея его в качестве значения по умолчанию. Вы можете использовать его как внутри класса, так и для наследования.
Я добавил проверки безопасности, чтобы предотвратить создание экземпляра вашего объекта с другими параметрами шаблона: Object<Type::Car, Type::Person>
. Для этого я добавил третий параметр шаблона, который является шаблоном типа со значением enable_if
в качестве значения по умолчанию. Вы получите ошибку во время компиляции, если попытаетесь создать экземпляр объекта с другими параметрами шаблона. Вторая проверка не позволяет вам иметь такие объекты: Object<Type::Car, Object::Car, int>
, потому что в этом случае компилятор обратится к основному шаблону, который будет утверждаться.
Без проверки безопасности становится все проще:
enum class Type { Car, Person, Truck };
template<Type TYPE>
struct ObjectConfig;
template<>
struct ObjectConfig<Type::Car>
{ };
template<>
struct ObjectConfig<Type::Person>
{ };
template<Type TYPE, Type DELEGATED_TYPE = TYPE>
struct Object;
template<Type DELEGATED_TYPE>
struct Object<Type::Car, DELEGATED_TYPE>
{
ObjectConfig<DELEGATED_TYPE> m_params;
};
template<Type DELEGATED_TYPE>
struct Object<Type::Person, DELEGATED_TYPE> : public ObjectConfig<DELEGATED_TYPE>
{ };
int main() {
Object<Type::Car> c;
Object<Type::Person> p;
}