Changing enum to next value [C++11]

As noted by Maroš Beťko, to add 1 to a variable, you have to cast the value to int and back:

activeDraw = static_cast<drawMode>(static_cast<int>(activeDraw) + 1);

If the enum is defined without the C++11 enum class syntax (like in the question's text), the casting to int is not necessary:

activeDraw = static_cast<drawMode>(activeDraw + 1);

To make it cycle back to zero, use integer arithmetic, modulo operator:

activeDraw = static_cast<drawMode>((activeDraw + 1) % (ATMOSPHERE + 1));    

To eliminate one ugly +1, add another element to the enum:

enum drawMode { ..., ATMOSPHERE, NUM_DRAW_MODES };
...
activeDraw = static_cast<drawMode>((activeDraw + 1) % NUM_DRAW_MODES);

You can also stuff this code into a operator++ if you use it very often:

drawMode operator++(drawMode& mode)
{
    mode = static_cast<drawMode>((mode + 1) % NUM_DRAW_MODES);
    return mode;
}

drawMode operator++(drawMode& mode, int) // postfix operator
{
    drawMode result = mode;
    ++mode;
    return result;
}

Overloading operators for enums is rarely used, and some people consider it overkill (bad), but it will make your code shorter (and arguably cleaner).


Since your enumerates don't have a forced value, you could "increase" them, and perform a modulo on the last item + 1 to reset to the first one when needed:

 activeDraw = drawMode((activeDraw+1) % (ATMOSPHERE+1));

BTW: also works in C language with a slight modification:

activeDraw = (activeDraw+1) % (ATMOSPHERE+1);

This is something you should write once, use many places.

boost has some operator libraries that might be useful. If you need to write your own, here is an example:

namespace EnumOps {
  // ADL helper.  See #define below for macro that writes
  // the "this enum should use enum ops" overload:
  template<class T>
  std::false_type use_enum_ops_f(T&&){return {};}

  // trait class that detects if we should be messing with this enum:
  template<class T>
  using use_enum_ops = decltype(use_enum_ops_f( std::declval<T>() ));

  // to-from underlying type:
  template<class E,
    std::enable_if_t< use_enum_ops<E>{}, int> =0
  >
  constexpr std::underlying_type_t<E> get_underlying(E e) {
    return static_cast<std::underlying_type_t<E>>(e);
  }
  template<class E,
    std::enable_if_t< use_enum_ops<E>{}, int> =0
  >
  constexpr E from_underlying(std::underlying_type_t<E> e) {
    return static_cast<E>(e);
  }

  // Clamps your Enum value from 0 to E::MAX_VALUE using modular arithmetic
  // You must include a MAX_VALUE in your enum.
  template<class E,
    std::enable_if_t< use_enum_ops<E>{}, int> =0
  >
  E clamp_max( std::underlying_type_t<E> e ) {
    constexpr auto max = get_underlying(E::MAX_VALUE);
    if (e < 0) {
      auto count = -(e-max+1)/max;
      e =  e + count*max;
    }
    return from_underlying<E>(e % max);
  }

  template<class E,
    std::enable_if_t< use_enum_ops<E>{}, int> =0
  >
  E& operator+=( E& e, std::underlying_type_t<E> x ) {
    e= clamp_max<E>(get_underlying(e) + x);
    return e;
  }
  template<class E,
    std::enable_if_t< use_enum_ops<E>{}, int> =0
  >
  E& operator-=( E& e, std::underlying_type_t<E> x ) {
    e= clamp_max<E>(get_underlying(e) - x);
    return e;
  }
  template<class E,
    std::enable_if_t< use_enum_ops<E>{}, int> =0
  >
  E operator+( E e, std::underlying_type_t<E> x ) {
    return e+=x;
  }
  template<class E,
    std::enable_if_t< use_enum_ops<E>{}, int> =0
  >
  E operator+( std::underlying_type_t<E> x, E e ) {
    return e+=x;
  }
  // no int - enum permitted, but enum-int is:
  template<class E,
    std::enable_if_t< use_enum_ops<E>{}, int> =0
  >
  E operator-( E e, std::underlying_type_t<E> x ) {
    e -= x;
    return e;
  }
  // enum-enum returns the distance between them:
  template<class E,
    std::enable_if_t< use_enum_ops<E>{}, int> =0
  >
  std::underlying_type_t<E> operator-( E lhs, E rhs ) {
    return get_underlying(lhs) - get_underlying(rhs);
  }
  // ++ and -- support:
  template<class E,
    std::enable_if_t< use_enum_ops<E>{}, int> =0
  >
  E& operator++( E& lhs ) {
    lhs += 1;
    return lhs;
  }
  template<class E,
    std::enable_if_t< use_enum_ops<E>{}, int> =0
  >
  E operator++( E& lhs, int ) {
    auto tmp = lhs;
    ++lhs;
    return tmp;
  }
  template<class E,
    std::enable_if_t< use_enum_ops<E>{}, int> =0
  >
  E& operator--( E& lhs ) {
    lhs -= 1;
    return lhs;
  }
  template<class E,
    std::enable_if_t< use_enum_ops<E>{}, int> =0
  >
  E operator--( E& lhs, int ) {
    auto tmp = lhs;
    --lhs;
    return tmp;
  }
}
// use this macro in the namespace of your enum
// passing it your enun name:
#define ENABLE_ENUM_OPS(...) \
  std::true_type use_enum_ops_f(__VA_ARGS__){return {};}
// Where you wnat to use ops, you must also
// using namespace EnumOps;

Example use:

namespace somewhere {
  enum class bob { A, B, C, MAX_VALUE };
  ENABLE_ENUM_OPS(bob)
}

int main() {
  using namespace EnumOps;
  auto x = somewhere::bob::A;
  ++x;
  std::cout << (x == somewhere::bob::B) << "\n";
  x+=3;
  std::cout << (x == somewhere::bob::B) << "\n";
  x-=4;
  std::cout << (x == somewhere::bob::A) << "\n";
}

live example.

This uses modest amount of C++14 -- the std::underlying_type_t<E>. Replace with typename std::underlying_type<E>::type. And similar for any other _t aliases I sneaked in.

It uses C++11 features that MSVC 2015 fails at miserably. Use a C++11 compiler to fix that problem. It may appear to initially work in MSVC 2015, but do not be fooled. I have not tried it on MSVC 2017.