简体   繁体   中英

How does template type deduction work with an overloaded function as the parameter

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?

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:

  1. Do not use an overloaded name, static_cast to the desired function type, or explicitly provide the type of T in the call to bar.
  2. Alter the overloads such that deduction will succeed for only one of the overloads. In other words, exclude overloads by deduction, not by substitution. See below for an example.
  3. Add another parameter which can deduce T.
  4. Pass the buck and avoid deducing T until a later point.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM