Why do conversion operators cause ambiguous overload when const-ref and value exist

无人久伴 提交于 2021-01-28 02:45:14

问题


I'm looking at a wrapping class, based on https://www.fluentcpp.com/category/strong-types/ The main difference is that I'm replacing the get() method with a explicit casting operator as this triggers questions during code review when used.

As you can see in the simplified code below, I have 3 overloads of the casting operator:

  • From const A & to int
  • From A && to int
  • From const A & to const int &

When writing: static_cast<int>(a), I expect the overload of const A & to int to be used. However, it seems to favor the int and the const int & overload equally. Why does it do so?

Similarly to this, it seems to allow const int &r = static_cast<const int &>(createA()); which I assume is a life-time bug. (assuming createA returns an A by value)


Simplified code at 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;
}

Compilation error:

<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:


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

and

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

are equally good conversions. a is a lvalue so both functions can be called. a is also not const so both functions will have to apply a const conversion to a, so they are both still equally good. All that is left is the "return type", int or const int&, but those are both equally good to create anint from.

You need to get rid of one of conversion operators, or remove the constness from

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

to turn it into

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

so non const lvalues give you a const reference.



来源:https://stackoverflow.com/questions/54161013/why-do-conversion-operators-cause-ambiguous-overload-when-const-ref-and-value-ex

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!