Re: template argument deduction for overloaded predicates
On 2012-11-06 16:48, Jens Auer wrote:
I have problem with template argument deduction when using an
overloaded function as a predicate for std::all_of. What I want to do
is the following:
#include <vector>
#include <algorithm>
struct A {};
struct B {};
bool p(A const&);
bool p(B const&);
void f()
{
std::vector<A> as;
bool b = std::all_of( as.begin(), as.end(), p);
}
, but the compiler complains that it cannot deduce the type
of the predicate parameter for std::all_of.
The compiler is right, it cannot deduce which overload you meant.
Consider the following simplified example
struct A {};
struct B {};
bool p(A const&);
bool p(B const&);
template<class F>
void deduce(F){}
void f()
{
deduce(p);
}
The same problem occurs here: There is no compile-time information about
the functor type required here.
I can strip this down to
template<typename T, typename P> void callP(T i, P f)
{
f(*i);
}
void f()
{
std::vector<A> as;
callP( as.begin(), p);
}
which does not compile with the same error, but I do not see the
reasoning behind this. My thinking is: The compiler has two candidates
and substition fails for the B overload because parameter type does
not match.
Your assumption about the substitution process is incorrect. In fact,
the substitution cannot take place, because the compiler cannot deduce
*which* name p you are referring to in the call expression. The compiler
does *not* even attempt to deduce what the result would have been for
each name p. Even if that were the case, *both* such deductions would
indeed succeed. The error would then happen when the template
*definition* becomes instantiated which is too late for any retrial.
Substitution failure essentially is a failure when attempting to
instantiate a function template declaration.
I believe your example is ruled by [temp.deduct.call] p6:
"When P is a function type, pointer to function type, or pointer to
member function type:
[..]
? If the argument is an overload set (not containing function
templates), trial argument deduction is attempted using each of the
members of the set. If deduction succeeds for only one of the overload
set members, that member is used as the argument value for the
deduction. If deduction succeeds for more than one member of the
overload set the parameter is treated as a non-deduced context."
In your example both "trial deductions" succeed and this makes the
situation equivalent to a non-deduced context.
Since substitution is not an error, the compiler should now
go on and consider the next function with the matching parameter and
come up with a single possible match.
The problem is that your assumptions are based on a different deduction
model as specified.
HTH & Greetings from Bremen,
Daniel Kr?gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]