0

I have a function to change the state of an LED that takes in an enum argument with three possible values:

enum class Command { Off, On, Toggle };

void led(Command);

I'd like to be able to use the led() function with bool arguments: led(true) or led(false).

I realize that I can overload the void led(Command) function with a void led(bool) but I feel like this shouldn't be necessary.

Specifically, I'm thinking I should be able to define an operator that provides an explicit conversion from bool to Command. I haven't been able to find the syntax for this. My current best guess is:

inline constexpr operator Command(bool on) { return on ? Command::On : Command::Off; }

But it seems the operator overloads can only be declared inside classes? I can see how I could do this with a full class instead of an enum class, but that seems heavy here.

Is what I want to do possible?

Cameron Tacklind
  • 5,764
  • 1
  • 36
  • 45
  • 2
    That's the typical use case of function overloading, I doubt there's a better solution than `void led(bool)` – MatG Apr 02 '21 at 18:17
  • `enum class` only does so much. If you want it to have behavior, you may want to use `class Command { public: enum Op { Off, On, Toggle}; /*...*/};` and then you have a place to add in member functions, conversion constructors, `explicit operator bool`, et cetera. – Eljay Apr 02 '21 at 18:18

2 Answers2

1

I think that function overloading was designed exactly for this need: same action, different input types. I'd change the method name though, usually a verb makes the action clearer and improves the code readability.

Something like:

void set_led(Command);
void set_led(bool on){
    if(on)
        return set_led(On);
    return set_led(Off);
}
Captain Giraffe
  • 14,407
  • 6
  • 39
  • 67
MatG
  • 574
  • 2
  • 7
  • 19
  • Well, you wouldn't `return` the results of calling a void function, but otherwise yeah. – Nathan Pierson Apr 02 '21 at 18:57
  • 2
    @Nathan that's perfectly legal in c++ (https://ideone.com/GroC04). Mat's just making it so they don't need an `else` statement or a separate line for the `return`. – scohe001 Apr 02 '21 at 18:59
  • Huh, didn't know that! Neat. – Nathan Pierson Apr 02 '21 at 19:02
  • @Nathan Ehm, I didn't knew that either, that's captain-giraffe 's code! :-) Since he has several orders of magnitude more reputation than me, I have nothing to complain – MatG Apr 02 '21 at 19:07
  • Is there a reason to not use `set_led(on ? Command::On : Command::Off)`? Feels shorter and easier to read to me. – Cameron Tacklind Apr 03 '21 at 00:51
  • @CameronTacklind It is usually better write things once; if you like to write that in each call, well, you can, but I wouldn't be so happy if I were the code reviewer – MatG Apr 03 '21 at 05:52
  • @MatG I meant as the implementation of `set_led(bool on);` – Cameron Tacklind Apr 03 '21 at 20:10
  • @CameronTacklind Oh :-) As of the current function signature they are equivalent, it's just a matter of taste – MatG Apr 03 '21 at 21:14
1

The whole purpose of enum class that you're using is to prevent comparisons directly to int (which bool has an implicit conversion to). So as long as you're using an enum class, there's no easy way to do this implicitly.

That said, you can take advantage of the fact that your Off is the first item of the enum (it'll convert to int 0) and On is the second (which'll convert to 1). Since this matches the implicit bool to int conversions for false and true, you can do:

led(Command(true));
led(Command(false));

See it in action: https://ideone.com/iWrc3s


Alternatively, you can switch to just an enum instead of an enum class, which will allow your Command to be implicitly converted to an int. Since bool also has an implicit conversion to int, you can change your led() method to take an int and then call it directly with:

led(true);
led(false);

See it in action: https://ideone.com/HF0cxI

scohe001
  • 15,110
  • 2
  • 31
  • 51