Вы не можете принимать решения о времени компиляции для чего-то, что известно только во время выполнения (например, параметр, передаваемый компилятору).
Поэтому у вас есть два варианта:
1) генерировать исключение во время выполнения, когда вызывается неподдерживаемый метод
inline void do_Bar(){
if(model == KLM) throw runtime_exception("do_bar unsupported by device");
...
}
2) Создайте много классов, возможно, с помощью шаблонов, которые содержат только соответствующие методы. Один из способов сделать это заключается в следующем:
enum Model{ ABC , KLM , XYZ };
template<Model M>
class Device {
public:
Device(); // ctor
// Commands (encapsulate low-level instructions)
inline void do_Foo(); // supported by all models
template<Bool Dummy = true>
inline typename std::enable_if<Dummy && (M != KLM), void>::type do_Bar(); // unsupported by 'KLM'
};
Требуется параметр шаблона Dummy
, поскольку enable_if
зависит от SFINAE, который будет работать только в том случае, если сам метод является методом шаблона, а enable_if
зависит от параметра шаблона. Поскольку это параметр шаблона по умолчанию, его не нужно явно указывать при вызове метода, поэтому
Device<ABC> d;
d.do_bar();
все равно будет работать (поэтому никаких изменений в интерфейсе нет).
Я использовал std::enable_if
, который доступен только на C ++ 11, если у вас его нет, вам нужно либо использовать boost::enable_if
, либо написать его самостоятельно (это не то, что hard ).
Второй вариант имеет тот недостаток, что невозможно написать код, который не знает базовой модели. С положительной стороны это позволяет маскировать небольшие различия в предлагаемых интерфейсах посредством частичной специализации (или использования enable_if
) для получения различных реализаций для разных моделей.
boost::enable_if
отличается от std::enable_if
тем, что в качестве первого параметра он принимает тип вместо логического. Таким образом, можно использовать boost::enable_if_c
, который работает так же, как std::enable_if
, или использовать boost::enable_if
в сочетании с boost::integral_constant
(который является частью черт типа Boost, поэтому включите boost/type_traits.hpp
):
template<Bool B> typename boost::enable_if<boost::integral_constant<bool, B && (M != KLM)>, void>::type do_bar();