简体   繁体   中英

Can I have an enum with unlabelled values in C++?

Basically I want to restrict variables to the values 0, 1 or 2.

I have tried doing this with the following:

enum Value
{
    0,
    1,
    2
};
Value var;

But this is a compile error because the enum values are unlabelled. It just makes the code less readable to assign names like "ZERO", "ONE" and "TWO" rather than referring to the values as 0, 1 and 2. Is there any way around this or should I just get rid of the enum and enforce the rule elsewhere?

If you want to use enum , then you need to name them. Since you're just working with integer values, and you apparently want them to actually represent integer values, your best bet is it use an int parameter, and do a quick check at the top of the method. A comment on the method specifying this constraint would be welcome.

Note that if your values actually correspond to non-numeric settings, then you should just come up with good names and use the enum

Just because you add identifiers for the values doesn't mean you have to use them... you can use Value(0) , Value(2) etc. if that's more convenient, but there is a danger: enum doesn't restrict the value stored to those listed... eg it won't protect you against Value(3) .

Inside structs/classes you can use bit fields to restrict the storage used for numbers, but even then: - the range has to correspond to either the signed or unsigned values possible in the number of bits requested - attempts to assign other values will result in high order bits being removed rather than any kind of compile- or run-time error

If your intention is to create a distinct type that enforces a restricted values 0 through 2, then you need a class with specialised constructor and assignment operators:

template <int MIN, int MAX>
class Bound
{
  public:
    explicit Bound(int n) { *this = n; }

    Bound& operator=(int n)
    {
        if (n < MIN or n > MAX)
            throw std::runtime_error("out of bounds");
        n_ = n;
        return *this;
    }
    Bound& operator+=(int n) { *this = n_ + n; }

    // should "+" return int or Bound?  entirely usage dependent...
    Bound operator+(int n) { return Bound(n_ + n); }

    // -=, -, *=, *, /=, /, %=, %, bitwise ops, pre/post ++/-- etc...

    operator int() const { return n_; }

  private:
    int n_;
};

You are looking for the builtin int type, AFAICT

If you really want to behave like a Java programmer use ADT religiously, you can always:

template <typename ordinal=int>
struct Value
{
    ordinal _val;
    /*implicit*/ Value(ordinal val) : _val(val) {}
    /*implicit*/ operator const ordinal&() const { return _val; }
    /*implicit*/ operator       ordinal&()       { return _val; }
};

int main()
{
    Value<> x = 3;
    int y = x;
    x = y;

    x += 17;
    x++;

    return x;
}

This will return 22

Of course, it is entirely possible to make the Value<> less generic and more useful in many ways, but you didn't really tell us anything about what you want with that

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM