std:: включить if, специализацию шаблона и наследование
Я хотел бы спросить вас о некоторых советах относительно этого кода. Это работает, но я думаю, что это может быть написано более элегантным способом. Это часть кода C++11, так что имейте это в виду, когда вы его компилируете;)!
#include <iostream>
#include <type_traits>
#include <typeinfo>
using namespace std;
class A {};
class B: public A {};
class C {};
class D: public C {};
class E: public A, public C {};
template<class T, typename = void>
class Example;
template<class T>
class Example<T, typename enable_if<is_base_of<A, T>::value and not is_base_of<C, T>::value>::type>
{
public:
string a() const
{
return string(typeid(T).name()) + " have A as base class";
}
};
template<class T>
class Example<T, typename enable_if<not is_base_of<A, T>::value and is_base_of<C, T>::value>::type>
{
public:
string b() const
{
return string(typeid(T).name()) + " have C as base class";
}
};
template<class T>
class Example<T, typename enable_if<is_base_of<A, T>::value and is_base_of<C, T>::value>::type> :
public Example<A>,
public Example<C>
{
};
int
main()
{
Example<B> example1;
Example<D> example2;
Example<E> example3;
cout << example1.a() << endl;
//cout << example1.b() << endl; It must raise a compile error
//cout << example2.a() << endl; It must raise a compile error
cout << example2.b() << endl;
cout << example3.a() << endl;
cout << example3.b() << endl;
}
Как вы можете видеть, я пытаюсь написать шаблон класса, который может обрабатывать классы, производные от A и C. Проблема заключается в том, что A и C либо наследуются как класс E. На самом деле мы могли бы также иметь что-то вроде этот...
template<class T>
class Example<T, typename enable_if<is_base_of<A, T>::value> { /* ... */ };
template<class T>
class Example<T, typename enable_if<is_base_of<C, T>::value> { /* ... */ };
...но он потерпит неудачу, когда класс (например, E) наследует либо A, либо C.
Есть идеи для лучшего кода? Спасибо
1 ответ:
Проще всего использовать
static_assert
.template <typename T> class Example { public: std::string a() const { static_assert(std::is_base_of<A, T>::value, "T must derive from A to use a()"); return std::string(typeid(T).name()) + " have A as base class"; } std::string b() const { static_assert(std::is_base_of<C, T>::value, "T must derive from C to use b()"); return std::string(typeid(T).name()) + " have C as base class"; } };