7

I found a strange behaviour, when compliling my code with G++ (gcc 4.8.1 and MinGW 4.8.2 with -std=gnu++1y flag). In spirit of SSCCE I isolating the following snippet:

struct C
{

    template< typename X >
    auto
    f(X &&) const &
    { ; }

    template< typename X >
    auto
    f(X &&) &
    { ; }

    template< typename X >
    auto
    f(X &&) &&
    { ; }

};

int main()
{
    int i{};
#if 1
    C{}.f(i);
#endif
#if 1
    C c{};
    c.f(i);
#endif
    return 0;
}

It gives an error:

main.cpp: In function 'int main()':
main.cpp:29:10: error: call of overloaded 'f(int&)' is ambiguous
     c.f(i);
          ^
main.cpp:29:10: note: candidates are:
main.cpp:6:5: note: auto C::f(X&&) const & [with X = int&]
     f(X &&) const &
     ^
main.cpp:11:5: note: auto C::f(X&&) & [with X = int&]
     f(X &&) &
     ^
main.cpp:16:5: note: auto C::f(X&&) && [with X = int&]
     f(X &&) &&
     ^

But in case of #if 1 and #if 0, or #if 0 and #if 1 it compiles normally. Also if I replace all auto's with void's, then all compiles successfully too.

Is it bug, or just my misleading?

Tomilov Anatoliy
  • 15,657
  • 10
  • 64
  • 169
  • Correct me if I'm wrong, but this looks like the perfect forwarding mechanism (the deducation rules for rvalue references for C++11) is screwing you up. http://stackoverflow.com/questions/3582001/advantages-of-using-forward. Basically, in `template void foo(T&& t)`, the `T&&` actually acts as a "universal" reference rather than a rhr. The actual deduction rules are...super confusing to me though. – IdeaHat Apr 23 '14 at 15:53
  • Another link: http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers – IdeaHat Apr 23 '14 at 15:54
  • 1
    @MadScienceDreams it not matters much, because if we substitute all occurences of `X &&` to `X const &`, then everything remains the same. – Tomilov Anatoliy Apr 23 '14 at 15:56
  • 6
    This is almost certainly a bug in the interaction between ref-qualifiers and return type deduction in g++. [clang at Coliru (post 3.4 trunk version) compiles the program without complaint](http://coliru.stacked-crooked.com/a/c8152dcf3e8f7455). [g++ at Coliru (4.8.2) refuses to compile it even with the members non-templated](http://coliru.stacked-crooked.com/a/682de1f3fe6567d7). It would be nice if someone could run it past 4.9. – Casey Apr 23 '14 at 15:58
  • @MadScienceDreams this code is pretty simple as compared with its prototype *bitbucket.org/insituc/variant*. – Tomilov Anatoliy Apr 23 '14 at 16:42

1 Answers1

4

g++ 4.8.2 has the same problem with the even simpler (Live at coliru):

struct A {
    auto f() & {}
    auto f() && {}
};

int main() {
    A{}.f();
    A a;
    a.f();
}

despite the program obviously being correct. It appears to be a bug in the interaction between ref-qualifiers and return type deduction: presumably the deduction process is stripping the qualifiers from the implicit object argument before handing them off to overload resolution.

I have reported this as GCC bug 60943.

Casey
  • 41,449
  • 7
  • 95
  • 125