简体   繁体   中英

Why do I have to explicitly cast an enum that I have specified the underlying type for?

I recently learned that I can specify the underlying type of an enumerator in C++11.

I've noticed that I can't for example use an enumerator with an underlying type of uint16_t as an argument for a uint16_t parameter. See the following example:

#include <stdint.h>

enum class Apples : uint16_t
{
    GRANNY_SMITH = 1
};

class AppleWatcher
{
    uint16_t m_apple;
public:
    AppleWatcher(const uint16_t apple) : m_apple(apple) {};

};

int main()
{
    AppleWatcher(static_cast<uint16_t>(Apples::GRANNY_SMITH));  // This works

    AppleWatcher(Apples::GRANNY_SMITH); // Compiler error here

    return 0;
}

I still have to explicitly cast to the underlying type to use it in such cases, so what is the purpose of this feature?

This is a type safety feature. Implicit conversions have a long history of associated issues in C++, have a look at Stephen Dewhurst's book "C++ Gotchas" - the longest chapter is that on conversions.

Recall that an enumeration is nothing but a way to bind a constant value to a comprehensible name. This way, there is a finite, documented set of possible values, and by an implicit conversion, you massively extend the domain without giving any notice. Example:

void f(uint16_t arg); // arg can have 65536 different values

enum class Apples  : uint16_t { GRANNY_SMITH = 1 }; // one possible value

If this compiles:

f(Apples::GRANNY_SMITH);

you have just given up the restrictiveness without giving notice. Instead,

f(static_cast<uint16_t>(Apples::GRANNY_SMITH));

is clearer and uglier. The clumsy nature of the cast tells you "why do you even do it?", and answering this question shouldn't be too easy. You created the enumeration to refer to possible values by typing out their associated names, right?

According to this documentation page:

There are no implicit conversions from the values of a scoped enumerator to integral types, although static_cast may be used to obtain the numeric value of the enumerator.

So in order to compile your code you need to explicitly cast the value, ie:

AppleWatcher(static_cast<uint16_t>(Apples::GRANNY_SMITH));

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