views:

68

answers:

2

I have the following piece of code, that gives an error on the first usage form of pred2. I was hoping if someone could explain why this particular usage is incorrect, as I think pred3 usage is similar.

#include <algorithm>

bool pred1(const int&) { return true; }

template<typename T>
bool pred2(const T&) { return true; }

struct pred3
{
   template<typename T>
   bool operator()(T&) { return true; }
};

int main()
{
   int A[] = { 2, 0, 4, 6, 0, 3, 1, -7 };
   const int N = sizeof(A) / sizeof(int);

   std::count_if(A, A + N, &pred1);      //ok
   std::count_if(A, A + N, &pred2);      //error
   std::count_if(A, A + N, &pred2<int>); //ok
   std::count_if(A, A + N, pred3());     //ok
   return 0;
}

http://codepad.org/LRqY3Joq

+4  A: 

pred2 is a normal function template and compiler needs to instantiate it using a particular type which can be existing type or user defined type.

Since in first usage, compiler is not able to deduce T argument from empty specification. It will flag an error.

With second usage, its right, as you have specified by which compiler deduces T templete argument to int through explicit template specification.

Pardeep
+3  A: 

If I understand correctly how these things works, the problem is that in the first three cases you're passing a pointer to a function, that, for its very nature, must point to a well-defined overload of a function, which doesn't apply to line 20, since there you're specifying a whole class of functions (each of which, by the way, has to be explicitly generated by the compiler when needed). The type deduction rules don't apply here, since, if you pass a function pointer, all the games are closed before the count_if body is evaluated (the type of the function pointer has to be well-defined before the count_if template instantiation).

At line 21, instead, you're specifying exactly which function you're passing, in facts the compiler instantiates the template for the int type and passes a pointer to that function.

At line 22 a completely different thing is going on. You're passing a well-defined object type to count_if. In the body of count_if then, when operator() is called, the compiler has all the information to deduce the template argument to it, since it is actually calling it and has real parameters from which it can perform the type deduction.

Matteo Italia