假设我想创建一个对某些常规类型起作用的仿函数。 例如
template<typename Ape>
class functor1
{
void operator()(Ape& m)
{
// Do something to m
}
};
这是为我做事的标准方式。但是,我还有另一种方式:
class functor2
{
template<typename Ape>
void operator()(Ape& m)
{
// Do something to m
}
};
第二种方法的优点是我不必明确说明模板的类型。
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?
}
第二个版本是否有效?或者我错过了什么?如果有效,第一种方法有什么好处吗?
答案 0 :(得分:3)
明显不同的是,在第一种情况下,您明确指定类型,在第二种情况下,编译器将在实际调用的上下文中为您推导出类型。但是,在您的具体示例中,它可能没有任何实际区别。
如果您的类中包含多个成员函数,则第一个变体将“修复”所有这些函数的相同模板参数,而在第二个变体中,将为每个成员函数独立推导出该参数。
当从多个上下文调用单个成员函数时也是如此:每个上下文将在第二个变体中执行其自己的模板参数推导。
根据你的意图,它可能好或不好。
如果您的函数通过值(或const
引用)接受其参数,则在第一个变体中,您可以为参数指定与存储在容器中的类型不同的类型。例如,您可以为long
创建一个仿函数,并将其应用于int
的容器。这在第二种变体中是不可能的。
例如,如果您的chimpanzee
类是多态的,派生自animal
,那么您可以使用functor1<animal>
来迭代此类容器。在第二个版本中,模板参数将作为chimpanzee
推导出来,而不是animal
。
如果您的类具有数据成员,则第二个变体将确保成员函数的所有特化都共享相同的数据(如果使用相同的仿函数对象)。在第一个变体中,每个特化都是一个不同的类,它有自己的数据。
答案 1 :(得分:1)
对于没有状态的算子,这应该是相同的。经常(比较)你需要在仿函数中存储相同类型的另一个对象/ ref /指针,在这种情况下你的第二个选项不起作用。请注意,如果您的仿函数确实需要构造函数参数,您可以创建一个像make_<foo>
这样的自由函数make_pair
来为您推导出类型并再次减少输入。
答案 2 :(得分:1)
就像范围界定:在functor1
中,类Ape
中的任何内容都可以使用类型functor2
(对于成员声明,参数和返回类型类型,特征或其他类型),而在Ape
中},operator()
仅表示functor1
范围内的内容。简而言之:
Ape
在创建时需要了解functor2
。 Ape
在调用之前无需了解functor1
。 Ape
中的所有内容都知道operator()
。functor2
中只有Ape
知道functor1
。Ape
个实例仅适用于单一类型的functor2
。Ape
实例适用于任何类型的{{1}}。