首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在C++中不编译转换为枚举类型?

如何在C++中不编译转换为枚举类型?
EN

Stack Overflow用户
提问于 2011-01-18 15:08:09
回答 3查看 493关注 0票数 1

我有一个“更好的”枚举课程

  1. 不能包含无效的值,并且
  2. 除非枚举值未显式设置,否则无法使用,

如下所示:

代码语言:javascript
复制
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");
        }
}; 

这允许我编写以下代码:

代码语言:javascript
复制
Symmetry s1(Symmetry::SYMMETRIC);
Symmetry s2;
s2 = Symmetry::HERMITIAN;
Symmetry s3;
if (Symmetry::GENERAL == s3) // throws

我的问题是编译器允许构造如下:

代码语言:javascript
复制
Symmetry s1((Symmetry::Type)18); // throws
Symmetry s2;
s2 = (Symmetry::Type)18; // throws

我通过抛出异常来解决这个问题,但我希望这样的代码根本不编译(编译时错误)。有办法处理这个问题吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-01-18 15:24:21

这可能是一个糟糕的解决方案,但它会解决你眼前的问题。与其拥有内部枚举类型,不如定义一个带有私有构造函数的小助手类,并使外部类成为朋友。然后,"enum“值可以是外部类中的静态const成员。就像这样:

(免责声明:未经测试,因此可能存在各种编译问题,但您应该了解)

代码语言:javascript
复制
class Symmetry
{
public:
    class Type
    {
    private:
        Type() {};
        friend class Symmetry;
    };

    static const Type GENERAL;
    static const Type SYMMETRIC;
    static const Type HERMITIAN;
};

您需要某种方法来确定等式,但这应该相当容易。

票数 4
EN

Stack Overflow用户

发布于 2011-01-18 15:59:55

我尝试使用模板:(测试。不过,这是可以进一步改善的!)

代码语言:javascript
复制
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

用法:

代码语言:javascript
复制
int main()
{
    Symmetry<0> e0;                   
    Symmetry<e0.HERMITIAN> e1;           

    switch (e1)
    {
    case e0.HERMITIAN:
        {
            cout << "It's working" << endl;
        }
        break;
    }
}
票数 1
EN

Stack Overflow用户

发布于 2011-01-18 15:25:52

不是的。如果您允许使用任何强制转换,就像上一个示例所做的那样,那么总有一些强制转换可以用来颠覆您的类型。

解决方案是不习惯使用这些强制转换,并且非常可疑地考虑任何不加区分地使用这些强制转换的代码。把这种类型的投射看作是你武器库中的核弹:拥有它是很重要的,但是你总是小心地处理它,而且从来不想部署它。

您的编译器有哪些用于转换的警告选项?您正在使用哪些衣棉工具可以检测到这种滥用的类型?

也就是说,您似乎真的想隐藏内部Type,这样用户就不会那么想使用它了。意识到这一点,它是将该类型的名称改为私有。,即使没有防止所有的演员误用,只要稍微修改一下原版:

代码语言:javascript
复制
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,因为使用未初始化的值应该事先是可以预防的,因此属于后一类。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4725664

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档