为什么当const-ref和value存在时转换运算符会导致模棱两可的重载

时间:2019-01-12 15:28:01

标签: c++ type-conversion c++17

我正在研究基于https://www.fluentcpp.com/category/strong-types/的包装类,主要区别在于,我正在用显式强制转换运算符替换get()方法,因为这会在使用代码时触发问题。

如下面的简化代码所示,我有3个重载的Cast运算符:

  • const A &int
  • A &&int
  • const A &const int &

在编写static_cast<int>(a)时,我希望使用const A &int的重载。但是,似乎同样赞成intconst int &重载。 为什么这样做?

与此类似,它似乎允许const int &r = static_cast<const int &>(createA());,我认为这是一生的错误。 (假设createA按值返回A)


Compiler Explorer中的简化代码:https://gcc.godbolt.org/z/YMH9Ed

#include <utility>

struct A
{
    int v = 42;
    explicit operator int() const & { return v; } // Removing this line works
    explicit operator int() && { return std::move(v); }
    explicit operator const int &() const & { return v; }
};

int main(int, char**)
{
    A a;
    int r = static_cast<int>(a);
    return r;
}

编译错误:

<source>:14:13: error: ambiguous conversion for static_cast from 'A' to 'int'
    int r = static_cast<int>(a);
            ^~~~~~~~~~~~~~~~~~~
<source>:6:14: note: candidate function
    explicit operator int() const & { return v; }
             ^
<source>:8:14: note: candidate function
    explicit operator const int &() const & { return v; }
             ^

1 个答案:

答案 0 :(得分:3)

explicit operator int() const & { return v; }

explicit operator const int &() const & { return v; }

转换效果同样好。 a是一个左值,因此可以调用两个函数。 a也不是const,因此这两个函数都必须将const转换应用于a,因此它们仍然同样出色。剩下的就是“返回类型”,intconst int&,但是从它们创建int都同样好。

您需要摆脱转换运算符之一,或删除常量  来自

explicit operator const int &() const & { return v; }

将其变成

explicit operator const int &() & { return v; }

因此非const左值会为您提供const引用。