views:

79

answers:

2

Hello,

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?

+1  A: 

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
Kirill V. Lyadvinsky
A: 

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.

deemoowoor
Well... It's still type casting.Actually I see this question on another site. I didn't come up with a good solution, except type casting. So I want to see if there is really a elegant method to do it.However, I will always prefer function object or lambda expr in such a situation. :)
hpsMouse