http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60631

            Bug ID: 60631
           Summary: [c++11] rvalue this member functions are ambiguous
           Product: gcc
           Version: 4.9.0
            Status: UNCONFIRMED
          Severity: major
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: paul at preney dot ca

Created attachment 32433
  --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=32433&action=edit
Brief code illustrating ambiguity bug.

The attached code using rvalue *this qualified member functions and fails to
compile although it should. The attached code produces the following ambiguous
error message which only arises from the use of a const rvalue object:

$ g++ -std=c++11 -Wall -Wextra gcc-rvalue-this-ambig-issue.cxx
gcc-rvalue-this-ambig-issue.cxx: In function ‘int main()’:
gcc-rvalue-this-ambig-issue.cxx:33:29: error: call of overloaded ‘get()’ is
ambiguous
     gobble(std::move(t).get()); // GCC reports this line is ambiguous!
                             ^
gcc-rvalue-this-ambig-issue.cxx:33:29: note: candidates are:
gcc-rvalue-this-ambig-issue.cxx:10:14: note: const int& Type::get() const &
   int const& get() const& { return i; }
              ^
gcc-rvalue-this-ambig-issue.cxx:15:15: note: const int&& Type::get() const &&
   int const&& get() const&& { return std::move(i); }
               ^
gcc-rvalue-this-ambig-issue.cxx:17:24: note: const volatile int&& Type::get()
const volatile &&
   int const volatile&& get() const volatile&& { return std::move(i); }
                        ^
$

with g++ v4.9.0 (Mar. 16). This error is also reported with g++ v4.8.1 and
v4.8.2. (Aside: Know the attached code compiles without issue with clang++
v3.4.) 

Significantly the above error shows g++ is also incorrectly considering an
lvalue ref qualified get() member even though the object is an rvalue due to
the use of std::move(). Finally, this ambiguity error ONLY occurs when Type is
decorated with const:

  {
    Type const t; 
    gobble(t.get());
    gobble(std::move(t).get()); // GCC reports this line is ambiguous!
  }

whereas in all other cases of Type, Type volatile, and Type const volatile
there is no ambiguity. The definition of Type has all rvalue *this and
cv-qualifiers overloaded for the get() member function, i.e., which implies
there should be no ambiguity which function gets called as there is always an
exact match.

struct Type
{
  int i;

  Type() : i(0) { }

  int& get() & { return i; }
  int const& get() const& { return i; }
  int volatile& get() volatile& { return i; }
  int const volatile& get() const volatile& { return i; }

  int&& get() && { return std::move(i); }
  int const&& get() const&& { return std::move(i); }
  int volatile&& get() volatile&& { return std::move(i); }
  int const volatile&& get() const volatile&& { return std::move(i); }
};

I cannot think of a good work-around other than to drop back (for the time
being) and not use rvalue *this members until this is fixed. I thank you for
looking at this issue.

Reply via email to