有没有办法将枚举自动序列化为int?每次我定义一个新的枚举并写
std::stringstream stream;
stream << myenum1;
stream >> myenum2;
编译器抱怨运算符&lt;&lt;和&gt;&gt;没有定义。你知道一种告诉编译器将枚举视为普通int的方法吗?
使问题更难的是,实际上,序列化是在模板中。像这样:
template <typename T>
void serialize(const T& value)
{
std::stringstream stream;
stream << value;
}
所以我无法添加任何演员表:( 也许我可以以某种方式专门化它?
谢谢。
答案 0 :(得分:4)
你可以通过boost的TypeTraits(is_enum)找出类型是否为enum。
然后,您可以将其与enable_if
/ disable_if
:
template <class T>
typename boost::disable_if<boost::is_enum<T> >::type serialize(const T&);
template <class T>
typename boost::enable_if<boost::is_enum<T> >::type serialize(const T&); //use casts here
但是,无法检查给定值是否对给定的枚举有效(除非您为给定的枚举类型编写特定的重载)。
答案 1 :(得分:3)
对于输出,<<
运算符会将任何枚举类型提升为最接近的int
或long
。 (§5.8/ 1,4.5 / 2)你不应该有任何问题,我不能用GCC或Comeau生产任何东西。如果我错了,请纠正我。
对于输入,您可以编写模板函数并通过将其隐藏在仅显式实例化的类中来禁用隐式实例化。
template< class E >
struct enum_traits {
friend std::istream &operator>> ( std::istream &is, E &e ) {
long i; // or intmax_t, whatever
std::istream &r = is >> i;
e = E( i );
return r;
}
};
enum my_enum { a, b, c };
template class enum_traits< my_enum >; // explicit instantiation
// "matching declaration" per 7.3.1.2/3:
std::istream &operator>> ( std::istream &, my_enum & );
这通过了GCC和Comeau。我找不到一种方法来争论命名空间和ADL以使其更方便。 (只有替代解决方案涉及每个枚举器的使用声明。)
但两个样板声明可以包装在一个宏中,或者无论如何它们都比再次编写整个函数更好!
答案 2 :(得分:1)
您是否尝试使用例如static_cast<int>(enumX)
?
答案 3 :(得分:1)
你知道一种告诉编译器将枚举视为普通int的方法吗?
这是不可能的(至少对于&gt;&gt;),因为它不是类型安全的(将int赋值给intum不是类型安全的。)
您可以做的一件事是提供运营商的重载&gt;&gt;和&lt;&lt;每个枚举,将为你做铸造。这是你将为每个枚举做一次的事情,这听起来比在你使用&gt;&gt; /&lt;&lt;&lt;&lt; (这里特别方便,因为你无法编辑使用这些操作符的地方)。
答案 4 :(得分:0)
使用C ++ 0x会更好,因为您将能够声明基础类型(例如unsigned short
)。
现在你必须使用一个约定,例如假设你的所有枚举值都可以存储在int
中,你可以将它序列化并反序列化为int,然后将其转换回来。
另一个问题当然是你的序列化程序:
std::stringstream stream;
stream << 1 << 2;
int a;
stream >> a;
assert(a == 12);
通常序列化涉及获取已知大小的二进制表示(或沿其序列化大小)。如果你不想自己处理,有图书馆:
两者都有纯文本和二进制表示(纯文本更容易调试)。