为什么switch和if语句与转换运算符的行为不同?

nya*_*108 15 c++ if-statement switch-statement conversion-operator explicit-conversion

为什么switchif语句在转换运算符方面表现不同?

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 **/ }
}
Run Code Online (Sandbox Code Playgroud)

编译错误是switch quantity is not an integerif声明中它被完美地识别为a bool.(GCC)

Clo*_*onk 17

语法是switch ( condition ) statement

condition - 整数或枚举类型的任何表达式,或者上下文可 隐式转换为整数或枚举类型的类类型的表达式,或者使用大括号或等于初始化程序的此类型的单个非数组变量的声明.

取自cppreference.

这意味着您只能对整数或枚举类型执行切换操作.为了使编译器能够隐式地将Wrapper转换为整数/枚举类型,您需要删除显式关键字:

显式说明符指定构造函数或转换函数(自C++ 11以来)不允许隐式转换

您还可以将Wrapper转换为int类型.

编辑地址@ acraig5075备注:

您必须小心哪个运算符是显式的,哪个是隐式的.如果两者都是隐式的,代码将无法编译,因为会有一个不确定性:

struct Wrapper
{
    operator int() { return 0; }
    operator bool() { return true; }    
};
Run Code Online (Sandbox Code Playgroud)

source_file.cpp:在函数'int main()'中:source_file.cpp:12:14:

错误:来自'Wrapper'的模糊默认类型转换

开关(w){

^ source_file.cpp:12:14:注意:候选转换

包括'Wrapper :: operator int()'和'Wrapper :: operator bool()'

消除歧义的唯一方法是进行演员表演.

如果只有一个运算符是显式的,则另一个运算符将被选择用于switch语句:

#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;
}
Run Code Online (Sandbox Code Playgroud)

输出:

 if is true 
case 1
Run Code Online (Sandbox Code Playgroud)

w已被隐式转换为1(true)(因为operator int是显式的)并且执行了case 1.

另一方面 :

struct Wrapper
{
    operator int() { return 0; }
    explicit operator bool() { return true; }    
};
Run Code Online (Sandbox Code Playgroud)

输出:

 if is true 
case 0
Run Code Online (Sandbox Code Playgroud)

w已被隐式转换为0因为运算符bool是显式的.

在这两种情况下,if语句都为true,因为在if语句内部对boolean w进行了上下文计算.

  • 但是如果bool和int强制转换都存在,那么仍然会存在歧义错误,即使两者都没有被声明为明确. (2认同)

Mar*_*ara 10

我认为解释了为什么switch声明不被接受,而if声明是:

在以下五个上下文中,预期类型为bool,如果声明bool t(e);格式正确,则构建隐式转换序列.也就是说,考虑显式的用户定义转换函数explicit T::operator bool() const;.这种表达e被认为是在语境上可转换为bool.

  • 控制if,while,for的表达式;
  • 逻辑运算符!,&&和||;
  • 条件运算符?:;
  • static_assert;
  • noexcept.

  • 当它引用后面的3个上下文(包括`switch`)时继续阅读:`注意,不考虑显式转换函数,即使它们在上下文转换中被认为是bool.但是我没有找到确切的原因这不是用`switch`实现的. (3认同)
  • 这里的"双重标准"(可以这么说)令我感到困惑. (2认同)