mrchance
mrchance

Reputation: 1175

c++ best way to define a type consisting of a set of fixed integers

i need to work with "indicator" variables I that may take on one of 3 integer values {-1, 0, 1}.

so i would rather not declare int I;

but rather indicator_t I;

where the type indicator_t ~ {-1, 0, 1}

if furthermore i can later use I in numerical expressions, as an integer (without casting?), that would be excellent.

question:

how should i define the type indicator_t?

Upvotes: 2

Views: 101

Answers (1)

Bitwize
Bitwize

Reputation: 11220

The simplest approach would be to convert the tri-state input into an enum class with 3 fixed discriminators:

enum class indicator_t {
    negative = -1,
    zero = 0,
    positive = 1,
};

There are several nice things with this approach:

  • It's simple, which makes it easy to understand and maintain
  • enum class makes it a unique type from ints, which allow both the enum and an integer to appear as part of an overload set, if needed
  • The enum logically has a cardinality of 3 (the type can accept 3 logical inputs). 1
    • This cardinality prevents code that would otherwise be like a != 22 even though 2 is never a possible input
  • When inputs are passed to a function accepting indicator_t, it's clear from the call-site the intention. Consider the difference between the following two code snippets:
    accept(1); // is this an indicator?
    accept(indicator_t::positive); // ah, it's an indicator
    

If you need to convert to / from numeric values, you can create simple wrappers for this as well:

auto to_int(indicator_t indicator) -> int
{
   return static_cast<int>(indicator);
}
auto to_indicator(int indicator) -> indicator_t
{
    if (indicator > 1 || indicator < -1) {
        // handle error. Throw an exception? 
    }
    return static_cast<indicator_t>(indicator);
}

1 Technically C++ enums can take on any integral value that fits in std::underlying_type_t<the_enum>, but this doesn't change that the logical valid set of inputs is fixed, which prevents developer bugs. Compilers will even try to warn on checks outside of the logical range.

2 Technically this could still be done, but you'd need to explicitly static_cast all the time -- so it would appear as a code smell rather than a silently missed logic bug.

Upvotes: 5

Related Questions