This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

__rvalref overloads causing ambiguities


Hi Chris,

It looks like your rvalue references that provide move semantics
can cause ambiguous overloads.

This is rejected using an (almost) up-to-date compiler with the so_7
branch:

#include <vector>

struct A
{
    template <typename B> operator B() const
    {
        return B();
    }
};

int main()
{
    A a;
    std::vector<int> v;
    v = a;                 // ERROR
}

The problem is that "template <class B> A::operator B() const" could be
called with [B = vector<int>] or with [B = rvalref<vector<int> >] and
there's no reason to prefer either of the conversions.

This isn't just academic, it breaks Boost.Assign:
http://tinyurl.com/cs4c4#assign-list_inserter-gcc-so7
http://tinyurl.com/cs4c4#assign-list_of-gcc-so7
http://tinyurl.com/cs4c4#numeric/ublas-test3-gcc-so7

(But apart from those three, all other Boost tests behave the same as
with normal mainline libstdc++, which is good.)


Could you add another level of indirection, so that going from A to
rvalref<vector> would require two user-defined conversions (which won't
happen implicitly) ?

I'm not sure you can, since "A::operator B" will always be able to match
rvalref<...> by a single conversion, and finding the overload set happens
before access-checking or checking whether a suitable ctor exists, or
most other reasons why the conversion to rvalref might fail.

To remove the rvalref overload from the overload set you'd have to use
SFINAE, but I think it would need A to be changed, which you can't
require since it's in user code.

This wouldn't be an issue with real rvalue refs in the language, since
there's no ambiguity between operator=(const vector&) and
operator=(vector&&) because both would use the same conversion from A to
vector<...>, and then the right one would be chosen based on the
"rvalue-ness" of the returned object.

Any clever ideas?


N.B. you get the same ambiguity for constructors that have an rvalref
overload:

    A a;
    std::vector<int> v(a);  // ERROR

However, this works:

    A a;
    std::vector<int> v = a;

because to use the rvalref ctor would require two user-defined
conversions (A to rvalref, then rvalref to vector).  At least, that's
how I understand it.

jon



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]