Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Class vs enum class as an index type

P0138R2 proposal begins with1

There is an incredibly useful technique for introducing a new integer type that is almost an exact copy, yet distinct type in modern C++11 programs: an enum class with an explicitly specified underlying type. Example:

enum class Index : int { };    // Note: no enumerator.

One can use Index as a new distinct integer type, it has no implicit conversion to anything (good!).

To convert Index to its underlying type it is useful to define

int operator*(Index index) {
    return static_cast<int>(index);
}

Another way to create Index type is to use old class:

class Index final {
public:
     explicit Index(int index = 0) : index_(index) { }

     int operator*() const {
         return index_;
     }

private:  
     int index_;
};

Both seem to be largely equivalent and can be used in the same way:

void bar(Index index) {
    std::cout << *index;
}

bar(Index{1});

int i = 1;
bar(Index{i});

Pro of enum class: the comparison operators are defined automatically, con of enum class: index value for the default constructed enum class can't be specified, it is always zero.

Are there other practical differences between these alternatives?


1 I changed uint32_t to int to avoid #include <cstdint>.
like image 848
Evg Avatar asked Aug 27 '18 19:08

Evg


People also ask

Can I use enum as array index?

In C++, I can define a enum and use the enum as the array index.

Is enum the same as class?

Difference between Enums and ClassesThe only difference is that enum constants are public , static and final (unchangeable - cannot be overridden). An enum cannot be used to create objects, and it cannot extend other classes (but it can implement interfaces).

Is enum class a class?

enum class is not a class definition - the combination of keywords is used to define a scoped enumeration, which is a completely separate entity from a class .

Can a class and enum have same name?

The enum value BAD resides in the general identifier scope, while the class type BAR resides in the class identifier scope. That is the reason why you are allowed to have both an enum value and a class with the same name: both names do not collide.


1 Answers

The alternative for strong types I use is a variation on NamedTypes by Jonathan Boccara. He nicely explains all of the details in multiple posts on his blog, see https://www.fluentcpp.com/2016/12/08/strong-types-for-strong-interfaces/

It's slightly more verbose in writing: using Index = NamedType<int, struct IndexTag, Comparable, ImplicitlyConvertibleTo<int>>;

When you construct this, you need to write something like Index{0}, though, the moment you use it as an index, it should automatically convert to the underlying type.

It has several advantages, including the ability to work on any type. The biggest disadvantage is that it's an external library you have to import instead of built-in functionality.

like image 87
JVApen Avatar answered Sep 26 '22 11:09

JVApen