Search code examples
c++templateslanguage-lawyerc++14trailing-return-type

deduce of argument of type class method (overloads by const qualifier) fails with trailing return type in gcc, but not in clang


Nothing clearer than an old good MCVE:

struct X {
  auto get(int) const -> int { return {}; }
  auto get(int) -> int { return {}; }
};

template <class R> auto f(auto (X::*)(int) const -> R) {}
//                        ^~~~                   ~~~~
//                        trailing return type

int main() {
  f(&X::get);
}

This fails in g++ (4.9.2 & 5.1.0). However if the old return type is used:

template <class R> auto f(R (X::*)(int) const) {}
//                        ^
//                        old return type

it works.

On clang (3.5.0) both variants work.

I know that trailing return type changes when the return type is inferred and the scope of it, so I wouldn't be quick to cast it as a gcc bug. So what does the standard says? Which compiler is right?


The most significant message in the error I think is

couldn't deduce template parameter ‘R’`

g++ full message:

main2.cpp: In function ‘int main()’:
main2.cpp:21:12: error: no matching function for call to ‘f(<unresolved overloaded function type>)’
   f(&X::get);
            ^
main2.cpp:18:25: note: candidate: template<class R, class auto:1> auto f(auto:1 (X::*)(int) const)
 template <class R> auto f(auto (X::*)(int) const -> R) {}
                         ^
main2.cpp:18:25: note:   template argument deduction/substitution failed:
main2.cpp:21:12: note:   types ‘auto:1 (X::)(int) const’ and ‘int (X::)(int)’ have incompatible cv-qualifiers
   f(&X::get);
            ^
main2.cpp:21:12: note:   couldn't deduce template parameter ‘R’
<builtin>: recipe for target 'main2' failed
make: *** [main2] Error 1

Solution

  • As pointed in the question this is a gcc bug which was beed fixed in version 6

    gcc.gnu.org/bugzilla/show_bug.cgi?id=69139