Я целый день боролся за то, чтобы найти действительно оптимальное решение, но, похоже, его нет.Мне нужно, чтобы мое перечисление было
- Неявно преобразуемым в целочисленный тип
- Используется в операторе
switch
- Используется в качестве нетипового параметра шаблона
In разработали следующий код, построенный по решению Говарда Хиннанта:
struct DataType
{
struct integral {
enum type { None, Single, Double, Int };
};
typedef typename integral::type integral_type;
explicit DataType(integral_type v) : val(v) {}
integral_type integral_value() const { return val; }
bool operator==(const DataType& s) const { return val == s.val; }
bool operator!=(const DataType& s) const { return val != s.val; }
static const DataType None;
static const DataType Single;
static const DataType Double;
static const DataType Int;
private:
integral_type val;
};
В файле .cpp
:
const DataType DataType::None (DataType::integral::None);
const DataType DataType::Single (DataType::integral::Single);
const DataType DataType::Double (DataType::integral::Double);
const DataType DataType::Int (DataType::integral::Int);
Как невведите параметр шаблона:
template <DataType::integral_type>
struct DataTypeTraits;
template <>
struct DataTypeTraits<DataType::integral::Single>
{
enum { size = 4 };
};
В переключателе:
size_t get_size(DataType type)
{
switch (type.integral_value()) {
case DataType::integral::Single: return DataTypeTraits<DataType::integral::Single>::size;
case DataType::integral::Double: return DataTypeTraits<DataType::integral::Double>::size;
case DataType::integral::Int: return DataTypeTraits<DataType::integral::Int>::size;
default: throw std::logic_error("Unknown data type.");
}
}
Не особенно здорово, но это так же хорошо, как и получается, я думаю ...