max66
max66

Reputation: 66230

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++?

Upvotes: 10

Views: 235

Answers (1)

Davis Herring
Davis Herring

Reputation: 40023

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.

Upvotes: 1

Related Questions