Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clang " couldn't infer template argument " whereas gcc / g++ can. Which is right?

Tags:

I have been trying to compile a project (which is fine using gcc/g++) with clang and compilation stuck on a template invocation. I've tried to create the simplest similar piece of code exhibiting the same error message. Here it is:

#include <vector>
#include <utility>
#include <iostream>

using namespace std;

int A( double in )
{
  return 1;
}

int A( int in )
{
  return 1;
}


template<class M, class T>
M test(T input, M (fun) (T) )
{
  return fun( input );
}



int main( int argc, const char *argv[] )
{
  cout << test( (int) 1, A ) << test( (double) 1.2, A ) << endl;
  return 0;
}

The error from clang (appears twice of course):

error: no matching function for call to 'test'
candidate template ignored: couldn't infer template argument 'M'

Gcc doesn't complain. Please note M is the return type and is always "int".

Does someone know which is right and why?

Thanks

like image 475
Max Avatar asked Jul 23 '13 10:07

Max


1 Answers

g++ is wrong. From C++11 [temp.deduct.type]p5:

The non-deduced contexts are: [...] - A function parameter for which argument deduction cannot be done because the associated function argument is [...] a set of overloaded functions, and [...] more than one function matches the function parameter type

This determination is made without regard to template parameters that might have been deduced elsewhere, so the fact that T must deduce as int is not relevant here. This makes the entire parameter M (fun)(T) a non-deduced context. Therefore M cannot be deduced, just as Clang claims.

g++ appears to incorrectly be using the 'T = int' deduction from the first function parameter when determining whether the second parameter is a non-deduced context. Reversing the order of the function parameters causes g++ to reject the code too:

int A(double);
int A(int);
template<class M, class T>
M test(M (fun) (T), T input) {
  return fun( input );
}
int main( int argc, const char *argv[]) {
  test(A, 1);
  test(A, 1.2); 
}
like image 160
Richard Smith Avatar answered Sep 27 '22 20:09

Richard Smith