【问题标题】:Multiple conversion functions as "operator auto" in class类中的“operator auto”多种转换功能
【发布时间】:2021-08-05 14:27:21
【问题描述】:

在下面的代码中

struct S {
    operator auto() { return 42; }
};

operator auto 等价于operator int,因为实际类型将从文字42 推导出来,并且该类型是int。如果我写42.5 而不是42,那么operator auto 将被解释为operator double,原因很明显。但是当我同时使用这两种编译器时,我得到了所有三个主要编译器(gcc、clang、msvc)的编译器错误:

struct S {
    operator auto() { return 42; }
    operator auto() { return 42.5; }
};

实际错误信息因编译器而异,但原因相同:“函数已定义”。

我无法在标准中找到为什么不能在一个类中同时使用 operator auto(具有不同的返回类型)。有人能指出标准的条款,其中该组转换功能被视为被禁止吗?

【问题讨论】:

标签: c++ type-conversion language-lawyer auto


【解决方案1】:

如果您在一个班级中只需要两个或三个operator autos,那么constdecltype(auto) 的技巧对您有用:

#include <iostream>

struct S 
{
    operator auto() { return 42; }
    operator const auto() { return 42.5; }
    operator decltype(auto)() { return 43.5f; }
};

int main()
{
   S s;
   std::cout << (int)s << '\n';
   std::cout << (double)s << '\n';
   std::cout << (float)s << '\n';
}

https://gcc.godbolt.org/z/hvbesaM4z

不幸的是,它不适用于三个以上不同的运算符。这是当前C++的局限。

【讨论】:

    【解决方案2】:

    基于 Fedor 的 answer 的想法,您甚至可以将 at least 12 auto like operators 与不同的限定符一起使用:

    #include <iostream>
    
    struct S {
        operator auto() { return 42; }
        operator auto() const { return '+'; }
        operator auto() volatile { return 44LL; }
        operator const auto() { return 45.5; }
        operator const auto() const { return 46.5f; }
        operator const auto() volatile { return 47L; }    
        operator volatile auto() { return 48ULL; }
        operator volatile auto() const { return 49U; }
        operator volatile auto() volatile { return 50UL; }
        operator decltype(auto)() { return 51.5L; }
        operator decltype(auto)() const { return 52.5L; }
        operator decltype(auto)() volatile { return 53.5L; }
    };
    
    int main() {
        const S s;
        std::cout << (int)(S)s << "\n";
        std::cout << (char)s << "\n";
        std::cout << (long long)(volatile S)s << "\n";
        
        std::cout << (double)(S)s << "\n";
        std::cout << (float)s << "\n";
        std::cout << (long)(volatile S)s << "\n";
        
        std::cout << (unsigned long long)(S)s << "\n";
        std::cout << (unsigned)s << "\n";
        std::cout << (unsigned long)(volatile S)s << "\n";
        
        std::cout << (long double)(S)s << "\n";
        std::cout << (long double)s << "\n";
        std::cout << (long double)(volatile S)s << "\n";
    }
    

    【讨论】:

      猜你喜欢
      • 2020-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-29
      • 2021-05-16
      • 2018-05-22
      • 2018-05-08
      相关资源
      最近更新 更多