Enumeration in C++ and other languages

Introduction

In programming, an enumeration is a data type that consists of a set of named values. In many programming languages, including C++, Java, and Kotlin, enumerations are implemented as a special type of class or structure, with each named value represented as a constant object of the enumeration type.

First, I discuss the basic concepts of enumeration in C++, then its implementation. Then the implementation of Java, Kotlin are discussed. Consequently, how the original concepts of enumeration in C++ expanded to other languages are described.

Concepts

Enumerations in all programming languages have the following concepts:

  • enumerator: the items in the enumeration
  • value representation: "Each enumerator is associated with a value of the underlying type." The values could be by default (increment of 1, starting from zero) or assigned.
  • underlying type: " is an implementation-defined integral type that can represent all enumerator values"
    • all enumerators in the enumeration must have the same type.
  • size: the data type size of the enumerator.
  • non-scoped enumeration: the enumeration values are part of the same scope as the enumeration type itself
    • Values of C++ unscoped enumeration type are implicitly-convertible to integral types.
    • The underlying type could be any of intunsigned intlong, unsigned longlong long, or unsigned long long.
  • scoped enumeration: the enumeration values are scoped within the same enum class.
    • Name of enumerator: Each enumerator becomes a named constant of the enumeration's type, which is contained within the scope of the enumeration, and can be accessed using scope resolution operator. Thus scope enumeration is also type-safe.
    • Values of scoped enumeration is not implicitly convertible to integral types, although C++ static_cast may be used to obtain the numeric value of the enumerator.

Notes: Kotlin only has scoped enumeration, which is enum class and sealed class.

Comparing enumeration in C++ and other languages

ConceptsC++Kotlint

C++ implementation

Unscoped enumeration

  • enum is declared with enum modifier. The value of the enumerator could be intialized or used default. The value should not be larger than INT_MAX.
  • If the values of the enumerators are not initialized, the values are then assigned to indexed value in same way as array index, starting from zero.

The following illustrates 2 enums, their enumerator's values, which is implicitly convertible to Int.

#include <iostream>

using namespace std;

int main()
{
    // plain enum 
    // underlying type is integer
    // associated values can be assigned but not be larger than int
    enum Color { red=12, green=20, blue=214 };
    // associated values are red_card=0, green_card=1, yellow_card=2
    enum Card { red_card, green_card, yellow_card };    
        
    Color color = Color::blue;
    Card card = Card::green_card;
    
    int num = color;             // enum is implicitly-convertible to integral types
    cout<<sizeof(num)<<endl;     // sizeof enumerator is int size
    // print associated values
    cout<<"Color::blue="<<num<<endl;
    cout<<"Card::green_card="<<card<<endl;
    
    cout<<"Color::blue+Card::green_card="<<num+card<<endl;    //not type safe
    
    // error: enumerator value for ‘food’ must have integral or unscoped enumeration type
    // enum MyEnum { food = 1.1, house='h', wife=3 };

    enum MyWishList{ food = 1, house='h', wife=3 };
    MyWishListe = MyEnum::house;
    // print out int value, ascii value of 'h'=104
    cout<<"MyWishList::house="<<e<<endl;

    return 0;
}

Scoped enumeration

  • the short coming of un-scoped enumeration is illustrated in line 23 of the above program. Although Color::blue and Card::green_card are of different enum, arithmetic operation could be performed on them. That is because they are not type-safe: the values are all implicitly convertible to int. The enumerator scope is the scope of the namespace that contains the enum. In this case, it is main function.
cout<<"Color::blue+Card::green_card="<<num+card<<endl;
  • enum class is type-safe. Yet its value are not implicitly convertible to Int.
  • Note: to print out enumerator, we must define << operator overload. The following print out the name of the enumerator, not the values:
#include <iostream>

enum class MyWishList{ food = 1, house='h', money=3 };

std::ostream& operator<<(std::ostream& os, const MyEnum2& e) {
    switch(e) {
        case MyWishList::food: os << "food"; break;
        case MyWishList::house: os << "house"; break;
        case MyWishList::money: os << "money"; break;
        default: os.setstate(std::ios_base::failbit);
    }
    return os;
}

int main() {
    MyWishList wish = MyEnum2::food;
    std::cout << "MyWishList::food = " << wish << std::endl;
    return 0;
}

References: c++ - How can I output the value of an enum class in C++11 - Stack Overflow

Kotlin Implementation

  • Kotlin only provide scoped enumeration. enum class modifier is used to declare and define an enum.
  • Kotlin also provide properties such as valueOf, name, and ordinal to ouput the values, the names or the index (position) of the enumerators within the enumeration.
enum class Direction { NORTH, EAST, SOUTH, WEST }

fun main(){

    val direction: Direction = Direction.EAST
    // print enumerator name
    println(direction.name)
    // print enumerator index
    println(direction.ordinal)
}
  • In addition, Kotlin enum has the following extra perks:

Enumeration as array

enum class Direction { NORTH, EAST, SOUTH, WEST}

fun main() {
    // access item with index 2 of the enum Direction
    println(Direction.values()[2])
}

Kotlin enumeration constructor:

Kotlin enumeration can use constructor to initialize values given to enumerators (enum constant)

enum class Direction (val value: Int) { 
    NORTH ( 100 ), 
    EAST  ( 200 ), 
    SOUTH ( 300 ), 
    WEST  ( 400 )
}


fun main(){

    val direction: Direction = Direction.EAST
    // print enumerator name
    println(direction.name)
    // print enumerator index
    println(direction.ordinal)
    // print enumerator value
    println(Direction.WEST.value)
}

Enum class implementing interface

Enum class is a class in Kotlin and can implement interface.

Enumerator defining Anonymous class

enum constant (enumerator) can declare their own anonymous class and methods to define the behaviours of the enumerator.

Leave a Reply

Your email address will not be published. Required fields are marked *