Вы должны сделать аргумент AEnum аргументом шаблона для do_sth:
template<AEnum e, typename T>
void do_sth(T t) { ... }
... и назвать его как a.do_sth<A::first>(0)
.
В качестве альтернативы, вы можете написать отдельные функции (do_sth_integral
, do_sth_container
, ...) или, если существует только один правильный курс действий для конкретного T, выведите «правильное» значение перечисления для данного T, используя приемы метапрограммирования / перегрузки.
Например, вот способ написания двух функций, которые, например, обнаруживают числовые типы и типы контейнеров:
//The extra dummy argument is invalid for types without a nested
//"iterator" typedef
template<typename T>
void do_sth(T t, typename T::iterator * = 0)
{
//container type code
}
//The dummy arg is invalid for types without a
//std::numeric_limits specialization
template<typename T>
void do_sth(T t,
typename boost::enable_if_c<std::numeric_limits<T>::is_specialized>::type * = 0)
{
//numeric type code
}
Конечно, это не удастся, если вы передадите T с итератором typedef и специализацией numeric_limits, или не имеет ни того, ни другого.
Если для определенного T существует только одно разумное действие, и трудно правильно угадать, какую перегрузку следует использовать для неизвестного T, тогда вы можете использовать класс признаков, который должен выполнять пользователь.явно специализировать или просто требовать, чтобы пользователи специализировали "impl" или диспетчерский класс.
Вы не можете написать функцию, которая делает что-то вроде 3.data()
, даже если этот кодПуть никогда не вызывается при запуске программы.Компилятор не знает, что он никогда не будет вызван, и в любом случае он нарушает систему типов языка так, чтобы вызвать диагностируемую ошибку.