我有一个“更好的”枚举课程
如下所示:
class Symmetry
{
public:
enum Type {
GENERAL, SYMMETRIC, HERMITIAN,
SKEW_SYMMETRIC, SKEW_HERMITIAN, UNINITIALIZED
};
Symmetry() { t_ = UNINITIALIZED }
explicit Symmetry(Type t) : t_(t) { checkArg(t); }
Symmetry& operator=(Type t) { checkArg(t); t_ = t; return *this; }
operator Type() const {
if (t_ == UNINITIALIZED) throw runtime_error("error");
return t_;
}
private:
Type t_;
void checkArg(Type t) {
if ((unsigned)t >= (unsigned)UNINITIALIZED)
throw runtime_error("error");
}
}; 这允许我编写以下代码:
Symmetry s1(Symmetry::SYMMETRIC);
Symmetry s2;
s2 = Symmetry::HERMITIAN;
Symmetry s3;
if (Symmetry::GENERAL == s3) // throws我的问题是编译器允许构造如下:
Symmetry s1((Symmetry::Type)18); // throws
Symmetry s2;
s2 = (Symmetry::Type)18; // throws我通过抛出异常来解决这个问题,但我希望这样的代码根本不编译(编译时错误)。有办法处理这个问题吗?
发布于 2011-01-18 15:24:21
这可能是一个糟糕的解决方案,但它会解决你眼前的问题。与其拥有内部枚举类型,不如定义一个带有私有构造函数的小助手类,并使外部类成为朋友。然后,"enum“值可以是外部类中的静态const成员。就像这样:
(免责声明:未经测试,因此可能存在各种编译问题,但您应该了解)
class Symmetry
{
public:
class Type
{
private:
Type() {};
friend class Symmetry;
};
static const Type GENERAL;
static const Type SYMMETRIC;
static const Type HERMITIAN;
};您需要某种方法来确定等式,但这应该相当容易。
发布于 2011-01-18 15:59:55
我尝试使用模板:(测试。不过,这是可以进一步改善的!)
template<int N>
struct Symmetry
{
enum Type
{
GENERAL, SYMMETRIC, HERMITIAN,
SKEW_SYMMETRIC, SKEW_HERMITIAN
};
template<Type e> struct allowed;
template<> struct allowed<GENERAL> { static const int value = GENERAL; };
template<> struct allowed<SYMMETRIC> { static const int value = SYMMETRIC; };
template<> struct allowed<HERMITIAN> { static const int value = HERMITIAN; };
template<> struct allowed<SKEW_SYMMETRIC> { static const int value = SKEW_SYMMETRIC; };
template<> struct allowed<SKEW_HERMITIAN> { static const int value = SKEW_HERMITIAN; };
allowed<(Type)N> m_allowed;
operator int()
{
return N;
}
};
Symmetry<0> e0; //okay
Symmetry<1> e1; //okay
Symmetry<100> e4; //compilation error!
Symmetry<e0.SKEW_HERMITIAN> e3; //okay
Symmetry<e0.SKEW_SYMMETRIC> e3; //okay用法:
int main()
{
Symmetry<0> e0;
Symmetry<e0.HERMITIAN> e1;
switch (e1)
{
case e0.HERMITIAN:
{
cout << "It's working" << endl;
}
break;
}
}发布于 2011-01-18 15:25:52
不是的。如果您允许使用任何强制转换,就像上一个示例所做的那样,那么总有一些强制转换可以用来颠覆您的类型。
解决方案是不习惯使用这些强制转换,并且非常可疑地考虑任何不加区分地使用这些强制转换的代码。把这种类型的投射看作是你武器库中的核弹:拥有它是很重要的,但是你总是小心地处理它,而且从来不想部署它。
您的编译器有哪些用于转换的警告选项?您正在使用哪些衣棉工具可以检测到这种滥用的类型?
也就是说,您似乎真的想隐藏内部Type,这样用户就不会那么想使用它了。意识到这一点,它是将该类型的名称改为私有。,即使没有防止所有的演员误用,只要稍微修改一下原版:
struct Symmetry {
enum {
UNINITIALIZED,
GENERAL, SYMMETRIC, HERMITIAN,
SKEW_SYMMETRIC, SKEW_HERMITIAN
};
private:
typedef decltype(UNINITIALIZED) Hidden;
Hidden _value;
public:
Symmetry(Hidden value = UNINITIALIZED) : _value (value) {}
Symmetry& operator=(Hidden value) { _value = value; return *this; }
operator Hidden() const {
if (_value == UNINITIALIZED) {
throw std::logic_error("uninitialized Symmetry");
}
return _value;
}
bool initialized() const { return _value != UNINITIALIZED; }
// required if you want to check for UNINITIALIZED without throwing in
// the above conversion
};这是一个完整的实现,没有遗漏或未知的细节,也没有初始化顺序的问题。唯一的警告是解密类型-使用预C++0x编译器,您将不得不使用一些特定于实现的东西,或者一个包装特定于实现的东西的图书馆。
还有一个较小的问题:从runtime_error改为logic_error,因为使用未初始化的值应该事先是可以预防的,因此属于后一类。
https://stackoverflow.com/questions/4725664
复制相似问题