Using enum in loops and value consistency

前端 未结 2 1128
傲寒
傲寒 2020-12-10 20:16

I\'m a big fan of C++\'s strong-typing features and what I like the most is to use enumerations while dealing with limited sets of data.

But enumerations lack some u

2条回答
  •  陌清茗
    陌清茗 (楼主)
    2020-12-10 20:49

    As you've noticed, enum in C++ is not an enumerated type, but something more complex (or more mixed). When you define an enum, you define in fact two things:

    1. An integral type with a legal range sufficient to contain an or of all of the enumerated values. (Technically: the range is 2^n - 1, where n is the number of bits necessary to hold the largest value.)

    2. A series of named constants having the newly defined type.

    (I'm not sure what happens with regards to the range if you explicitly specify an underlying type.)

    Given your enum Prime, for example, the legal values would be all integers in the range [0...64), even if all of these values don't have a name. (At least if you didn't specifically say that it should be an int.)

    It's possible to implement an iterator for enums without initializers; I have a program which generates the necessary code. But it works by maintaining the value in an integral type which is large enough to contain the maximum value plus one. My machine generated implementations of ++ on such an enum will assert if you try to increment beyond the end. (Note that your first example would require iterating h one beyond the last value: my implementation of the various operators does not allow this, which is why I use an iterator.)

    As to why C++ supports the extended range: enum are often used to define bit masks:

    enum X
    {
        a = 0x01,
        b = 0x02,
        c = 0x04,
        all = a | b | c,
        none = 0
    };
    
    X operator|( X lhs, X rhs )
    {
        return X((int)lhs | (int)rhs);
    }
    //  similarly, &, |= and &=, and maybe ~
    

    One could argue that this use would be better handled by a class, but the use of enum for it is ubiquitous.

    (FWIW: my code generator will not generate the ++, -- and the iterators if any of the enum values has an explicitly defined value, and will not generate |, & etc. unless all of the values have explicitly defined values.)

    As to why there is no error when you convert some value outside the legal range (e.g. 100, for X, above) is simply in keeping with the general philosophy inherited from C: it's better to be fast than to be correct. Doing extra range checking would entail additional runtime cost.

    Finally with regards to your last example: I don't see this as a realistic use of enum. The correct solution here is an int[]. While the C++ enum is rather a mixed breed, I would only use it as a real enumerated type, or for bit masks (and only for bit masks because it is such a widely established idiom).

提交回复
热议问题