Reputation: 21548
Look at this (simplified) example:
int foo(int) { return 0;}
double foo(double) { return 0.0; }
template <class T>
enable_if<is_integral<T>::value>
bar(T(*f)(T)) {}
int main()
{
bar(foo);
return 0;
}
My expectation was that the compiler will first try to instantiate the template for each overload, which would fail (SFINAE) for the second overload and therefore there would be only void bar(int(*f)(int)
left in the set of candidates, which would resolve using the first overload of foo
. That is not what happens. It fails with something like this:
no matching function for call to ‘bar(<unresolved overloaded function type>)’
couldn't deduce template parameter ‘T’
Is there any way to achieve something like this?
Upvotes: 3
Views: 272
Reputation: 7528
C++'s type deduction is very simplistic. The clauses [temp.deduct.call]/6.2 and [over.over]/1 describe ways in which an overloaded name can be used as an argument.
In your example, both the deductions would succeed (to T=int
and T=double
) and one substitution would fail. But the language requires only one deduction succeed.
You asked how to achieve it. Here are some options:
Example for #2:
tempate<class T> struct integral_wrapper { T t; }
integral_wrapper<int> foo(int);
double foo(double);
template<class T>
void bar(integral_wrapper<T> foo(T));
Example for #3:
template<class T>
void bar(T (*f)(T), T);
bar(foo, 0);
Example for #4:
struct foo_t
{
int operator()(int);
double operator()(double);
} foo;
template<class F>
void bar(F);
bar(foo);
Note that a generic lambda can be another approach for #4.
Depending on your usage, some of these may be more attractive than others. Approach #4 is particularly useful when passing arguments to STL algorithms.
Upvotes: 2