I\'m looking for a hacky kind of solution to the following problem: GCC 4.4+ accepts the following c++0x code:
enum class my_enum
{
value1,
value2
};
I just discovered a problem with James' good hack (which I have heretofore been using), and a fix to the problem. I discovered the problem when I tried to define a stream operator for my_enum.
#include <iostream>
struct my_enum {
enum type {
value1,
value2
};
my_enum(type v) : value_(v) { }
operator type() const { return value_; }
private:
type value_;
};
std::ostream&
operator<<(std::ostream& os, my_enum v)
{
return os << "streaming my_enum";
}
int main()
{
std::cout << my_enum::value1 << '\n';
}
The output is:
0
The problem is my_enum::value1
has different type than my_enum
. Here's a hack to James' hack that I came up with.
struct my_enum
{
static const my_enum value1;
static const my_enum value2;
explicit my_enum(int v) : value_(v) { }
// explicit // if you have it!
operator int() const { return value_; }
private:
int value_;
};
my_enum const my_enum::value1(0);
my_enum const my_enum::value2(1);
Notes:
int
.Do not use this solution. See the accepted answer by Howard for a better solution. I'm leaving this post here because Howard's answer refers to it.
If you need to be able to compile your code with a compiler that doesn't yet support a new, not yet standard or not yet widely implemented language feature, it's best to avoid using that language feature in your code.
That said, as a hack workaround, you can wrap the enum
in a struct
and use a pair of implicit conversions:
struct my_enum {
enum type {
value1,
value2
};
my_enum(type v) : value_(v) { }
operator type() const { return value_; }
private:
type value_;
};
I have been fighting for a whole day to find a truly optimal solution, but there doesn't seem to be one. I need my enum that is
switch
statementIn have come up with the following code, built upon Howard Hinnant's solution:
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;
};
In the .cpp
file:
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);
As non-type template parameter:
template <DataType::integral_type>
struct DataTypeTraits;
template <>
struct DataTypeTraits<DataType::integral::Single>
{
enum { size = 4 };
};
In a switch:
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.");
}
}
Not particularly great, but that's as good as it gets, I guess...