Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

g++ and clang++ different behaviour inferring the template return type of a function

Another "who's right between g++ and clang++?" question for C++ standard gurus.

The following program

#include <iostream>

void foo (int v)
 { std::cout << "foo(), int version (" << v << ')' << std::endl; }

void foo (double v)
 { std::cout << "foo(), double version (" << v << ')' << std::endl; }

template <typename T, typename R>
void bar (T v, R(*fn)(T))
 { fn(v); }

int main ()
 { bar(1, foo); }

compile and run with g++ (6.3.0, but also with 8.0.0 according Wandbox) but compiling it with clang++ (3.9.1, but also with 6.0.0 according Wandbox) I get the following error

tmp_002-11,14,gcc,clang.cpp:29:4: error: no matching function for call to 'bar'
 { bar(1, foo); }
   ^~~
tmp_002-11,14,gcc,clang.cpp:25:6: note: candidate template ignored: couldn't
      infer template argument 'R'
void bar (T v, R(*fn)(T))
     ^
1 error generated.

As usual the question is: who's right? g++ or clang++?

like image 837
max66 Avatar asked Jul 30 '17 12:07

max66


1 Answers

Clang is correct, but for a subtle reason: an overload set is allowed during template deduction, but deduction on that one argument must be able to select one of them for anything to be deduced. (If zero match, the overall deduction fails; if more than one does, deduction ignores that argument.) Here, both foos match R(*fn)(T), so R cannot be deduced from that argument (even though they would both agree on it), and thus not at all.

like image 129
Davis Herring Avatar answered Nov 07 '22 04:11

Davis Herring