Suppose I want to create a functor that acts upon some general type.
For example
template<typename Ape>
class functor1
{
void operator()(Ape& m)
{
// Do something to m
}
};
This has been the standard way of doing things for me. However, I also have another way:
class functor2
{
template<typename Ape>
void operator()(Ape& m)
{
// Do something to m
}
};
The advantage of the second approach is that I don’t have to explicitly state the type of the template.
int main()
{
std::vector<chimpanzee> chimps(100);
for_each(chimps.begin(), chimps.end(), functor1<chimpanzee>()); // Explicity state the type
for_each(chimps.begin(), chimps.end(), functor2()); // Less typing. Will it work?
}
Will the second version work? Or am I missing something? If it works are there any advantages to the first approach?
The obvious difference is that in the first case you specify the type explicitly, and in the second case it is the compiler that will deduce the type for you in the context of the actual call. However, in you specific example it might make no real difference at all.
If your class had multiple member functions in it, the first variant would “fix” the same template parameter for all of them, while in the second variant the parameter would be deduced for each member function independently.
The same is true when a single member function is called from multiple contexts: each context will perform its own template argument deduction in the second variant.
It could be good or not so good, depending on your intent.
If your function accepted its argument by value (or by
constreference), in the first variant you could specify a different type for the argument than the one stored in the container. For example, you could have created a functor forlongand applied it to the container ofints. This is not possible in the second variant.For example, if your
chimpanzeeclass was polymorphic, derived fromanimal, you could have used afunctor1<animal>to iterate over such container. In the second variant the template parameter will be deduced for you aschimpanzee, not asanimal.If your class had data members, the second variant would make sure that all specializations of member function(s) share the same data, if the same functor object is used. In the first variant each specialization is a different class, it gets its own data.