Я использую шаблоны для преобразования диапазона с проверкой диапазона из int в enum. Это выглядит так:
template<typename E>
E enum_cast(const int &source);
Функция шаблона размещена более или менее в корневой директории проекта. При определении нового перечисления, которому, как предполагается, будут присвоены значения из файла конфигурации, например:
enum ConfigEnum {
ConfigEnumOption1 = 'A'
, ConfigEnumOption2 = 'B'
, ConfigEnumInvalid };
ConfigEnum option = XmlNode.iAttribute("option");
Я определяю специализацию шаблона для этого конкретного типа перечисления в .cpp-файле для модуля, в котором это перечисление используется.
template<>
ConfigEnum enum_cast(const int &source) {
switch(source) {
case ConfigEnumOption1 : return ConfigEnumOption1;
case ConfigEnumOption2 : return ConfigEnumOption2;
default return ConfigEnumInvalid;
}
Теперь присвоение int для перечисления становится:
ConfigEnum option = enum_cast<ConfigEnum>(XmlNode.iAttribute("option"));
, который гарантирует, что enum всегда находится в допустимом диапазоне. Обратите внимание, что я не всегда контролирую эти перечисления, поэтому это кажется разумным и легко настраиваемым решением.
Во всяком случае, все это работает очень хорошо (хотя я не уверен, что весь приведенный здесь код верен, потому что я просто сейчас вызываю его из памяти)
Проблема связана с тем фактом, что было бы желательно использовать эту конструкцию "enum_cast" через кодовую базу всякий раз, когда для enum назначается in. После всего этого можно выполнить простую операцию поиска и замены. Конечно, я не хочу определять эти специализации для всех и каждого перечисления вокруг, но только для тех, которые нуждаются в проверке диапазона в данный момент. Я бы предпочел добавить специализации шаблонов для типов перечислений, когда возникнет такая необходимость, и использовать оператор присваивания, когда специализация не определена.
Таким образом:
InternalEnum internal = enum_cast<InternalEnum>(internal_integer);
будет эффективно вызывать internal = internal_integer. Я полагаю, что мне нужно сказать компилятору использовать определенную реализацию «по умолчанию» для всех перечисляемых типов, которые не имеют специализации.
Моя первая ставка заключалась в том, чтобы дать исходной функции шаблона такую реализацию:
template<typename E>
E enum_cast(const int &source) {
E copy = source;
return copy;
};
К сожалению, теперь это всегда вызывается вместо специализаций, заданных в .cpp-файлах вглубь дерева каталогов проекта.
Есть мысли?
Заранее спасибо
Arne