2

I've been experimenting with the enum class feature of C++ and successfully got the ++ operator to overload as follows:

enum class counter_t : uint8_t {VAL1 = 0, VAL2, VAL3, VAL4, END};

inline counter_t operator ++ (counter_t c, int) {
  counter_t c2;
  if (c == counter_t::END) {
    c2 = counter_t::VAL1;
  }
  else {
    c2 = (counter_t)((uint8_t)c + 1);
  }
  return (c2);
}

int main(void) {

  volatile counter_t x = counter_t::VAL1;
  x = x++;
  x++;

  while(1) {
    // Do stuff
  }
}

It is fairly straightforward. The "x=x++;" line works fine, however the "x++;" line does not. What is the correct form of the ++ operator function for the autoincrement version?

12
  • 1
    take argument counter_t c via reference and modify it Commented Jul 28, 2015 at 16:08
  • Umm... the ++ operator only takes one operand, doesn't it? Why do you have counter_t and int? Commented Jul 28, 2015 at 16:09
  • 2
    @Jashaszun It depends, prefix increment does not take an extra argument, but the postfix operator takes an extra dummy int argument, so it have a different function signature from the prefix operator. Commented Jul 28, 2015 at 16:13
  • 1
    Isn't x = x++; still undefined, even if operator++ is overloaded? Commented Jul 28, 2015 at 16:29
  • 1
    @jxh Nope, it's valid to write x = operator++(x,0); and therefore valid to write x = x++;. Function calls have more sequencing restraints than built-in operators. Commented Jul 28, 2015 at 16:39

2 Answers 2

4

You may use this to implement a prefix increment:

inline counter_t& operator ++ (counter_t& c) {
  if (c == counter_t::END)
      c = counter_t::VAL1;
  else
      c = counter_t(unsigned(c) + 1);
  return c;
}

Now, you can use the prefix increment to implement the postfix increment:

inline counter_t operator ++ (counter_t& c, int) {
  counter_t result = c;
  ++c;
  return result;
}

Test:

#include <iostream>
int main(void) {
    counter_t prefix = counter_t::VAL1;
    for(unsigned i = 0; i < 5; ++i)
        std::cout << unsigned(++prefix) << ' ';
    std::cout << '\n';

    counter_t postfix = counter_t::VAL1;
    for(unsigned i = 0; i < 5; ++i)
        std::cout << unsigned(postfix++) << ' ';
    std::cout << '\n';
}

Note: In each case the counter is taken by reference and gets modified.

Sign up to request clarification or add additional context in comments.

Comments

3

Just following the errors, the following code compiles runs and works fine on MSVC. Note the volatile and & in function parameters. Also c2 = c and a couple of modifications, to follow the ++ standard (return value, then increment). volatile is necessary only because you have x declared as volatile.

inline counter_t operator ++ (volatile counter_t &c, int)
{
    counter_t c2;

    if (c == counter_t::END)
        c2 = counter_t::VAL1;
    else
        c2 = static_cast<counter_t>(static_cast<uint8_t>(c) + 1);

    c = c2;

    return c2;
}

5 Comments

You fail to follow standards with x++. it should be {auto old = c; ++c; return old;} and use your function for ++x.
The volatile was in there to keep the compiler from optimizing the program to nothing (even at -O1). I turned it down to no optimization, and don't need the volatile.
Hey, that works!. I thought that the pass-by-reference should be in there somewhere, but didn't know about the static_cast. Thank you very much.
static_cast isn't important in this case. I bothered me because I had it underlined in VS as an warning "C style cast instead of C++". Try to avoid C style cast, they can be problematic sometimes.
hmmm it doesn't look like you know what volatile is for :(

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.