hpsMouse
hpsMouse

Reputation: 2014

How to use an overloaded function as an argument of function template?

I think everyone has experience working with a code like the following:

void fun(Type1&);
void fun(Type2&);
vector<Type1> vec;
for_each(vec.begin(), vec.end(), fun);

Of course that won't compile, because it's not clear which function to be passed. And what's your commonly-used solution to the problem?

I know this will work:

for_each(vec.begin(), vec.end(), (void(*)(Type1&))fun);

But any better ideas?

Upvotes: 2

Views: 170

Answers (2)

Andrei Sosnin
Andrei Sosnin

Reputation: 730

I'd like to second Kirill's answer. If fun() functions are implemented very similarly (same code involving different types), it's a good idea to rewrite them as one single template function. As an additional plus, you would get a possibility to elegantly specify the function you need.

It's usually recommended to use the C++ equivalent to the C-style type cast:

for_each(vec.begin(), vec.end(), reinterpret_cast<void(*)(Type1&)>(fun));

Even more appropriate is to use static_cast in this case:

for_each(vec.begin(), vec.end(), static_cast<void(*)(Type1&)>(fun));

since we want to hint the compiler to the proper type.

Although much more verbose, it's better simply for code maintenance reasons -- it's easier to search for such constructs in the code than for C-style type casts.

There is also a possibility to avoid using type casts in favor of an explicit template argument specification:

for_each<std::vector<A>::iterator, void(*)(Type1&)>(vec.begin(), vec.end(), fun);

-- although it's not very big improvement from the original code. As you can see, you have to explicitly specify the first template parameter as well.

Upvotes: 0

Kirill V. Lyadvinsky
Kirill V. Lyadvinsky

Reputation: 99685

One solution is to use template function:

template<typename T>
void fun(T&);
// specialize fun for Type1 and Type2
...
for_each(vec.begin(), vec.end(), fun<Type1>);

The better way is to use functor with template operator():

struct fun
{
  template<typename T>
  void operator()(T&) const;
};
...
for_each(vec.begin(), vec.end(), fun()); // T for operator() will be deduced automatically

Upvotes: 2

Related Questions