Why do switch
and if
statements behave differently with conversion operators?
struct WrapperA
{
explicit operator bool() { return false; }
};
struct WrapperB
{
explicit operator int() { return 0; }
};
int main()
{
WrapperA wrapper_a;
if (wrapper_a) { /** this line compiles **/ }
WrapperB wrapper_b;
switch (wrapper_b) { /** this line does NOT compile **/ }
}
The compilation error is switch quantity is not an integer
while in the if
statement it is perfectly recognized as a bool
. (GCC)
Main Difference between If-else and Switch Case The main differences between the two are: The if-else statement is used to choose between two options, but the switch case statement is used to choose between numerous options. If the condition inside the if block is false, the statement inside the else block is executed.
You can always convert a switch statement to an equivalent if statement. You can always convert an if statement to a switch statement. The break keyword must be used in a switch statement; otherwise, a syntax error occurs.
Sure can, see the example below (this is proof of concept and not tested). Note that you can also use a switch inside a switch, just like nested if statements.
switch is a type of conditional statement that will evaluate an expression against multiple possible cases and execute one or more blocks of code based on matching cases.
The syntax is switch ( condition ) statement
with
condition - any expression of integral or enumeration type, or of a class type contextually implicitly convertible to an integral or enumeration type, or a declaration of a single non-array variable of such type with a brace-or-equals initializer.
Taken from cppreference.
This means you can only do a switch case on an integer or enum type. For the compiler to be able implicitly convert Wrapper to integer / enum type you need to remove the explicit keyword :
The explicit specifier specifies that a constructor or conversion function (since C++11) doesn't allow implicit conversions
You can also cast Wrapper to int type.
Edit to adress @acraig5075 remarks :
You must be careful which operator is explicit and which is implicit. If both are implicit the code won't compile because there will be an amibiguity :
struct Wrapper
{
operator int() { return 0; }
operator bool() { return true; }
};
source_file.cpp: In function ‘int main()’: source_file.cpp:12:14:
error: ambiguous default type conversion from ‘Wrapper’
switch (w) {
^ source_file.cpp:12:14: note: candidate conversion
include ‘Wrapper::operator int()’ and ‘Wrapper::operator bool()’
The only way to remove the ambiguity is to do a cast.
If only one of the operator is explicit, the other one will be chosen for the switch statement :
#include <iostream>
struct Wrapper
{
explicit operator int() { return 0; }
operator bool() { return true; }
};
int main()
{
Wrapper w;
if (w) { /** this line compiles **/std::cout << " if is true " << std::endl; }
switch (w) {
case 0:
std::cout << "case 0" << std::endl;
break;
case 1:
std::cout << "case 1" << std::endl;
break;
}
return 0;
}
Output :
if is true
case 1
w
has been implicitly converted to 1
(true
) (because operator int is explicit) and case 1 is executed.
On the other hand :
struct Wrapper
{
operator int() { return 0; }
explicit operator bool() { return true; }
};
Ouput :
if is true
case 0
w
has been implicitly converted to 0
because operator bool is explicit.
In both case, the if statement is true because w
is evaluated contextually to a boolean inside the if-statement.
I think this explains why the switch
statement is not accepted, whereas the if
statement is:
In the following five contexts, the type bool is expected and the implicit conversion sequence is built if the declaration
bool t(e);
is well-formed. that is, the explicit user-defined conversion function such asexplicit T::operator bool() const;
is considered. Such expression e is said to be contextually convertible to bool.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With