C中的模板函子。类模板与功能模板

时间:2012-07-11 14:16:57

标签: c++ templates functor

假设我想创建一个对某些常规类型起作用的仿函数。 例如

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?
}

第二个版本是否有效?或者我错过了什么?如果有效,第一种方法有什么好处吗?

3 个答案:

答案 0 :(得分:3)

明显不同的是,在第一种情况下,您明确指定类型,在第二种情况下,编译器将在实际调用的上下文中为您推导出类型。但是,在您的具体示例中,它可能没有任何实际区别。

  1. 如果您的类中包含多个成员函数,则第一个变体将“修复”所有这些函数的相同模板参数,而在第二个变体中,将为每个成员函数独立推导出该参数。

    当从多个上下文调用单个成员函数时也是如此:每个上下文将在第二个变体中执行其自己的模板参数推导。

    根据你的意图,它可能好或不好。

  2. 如果您的函数通过值(或const引用)接受其参数,则在第一个变体中,您可以为参数指定与存储在容器中的类型不同的类型。例如,您可以为long创建一个仿函数,并将其应用于int的容器。这在第二种变体中是不可能的。

    例如,如果您的chimpanzee类是多态的,派生自animal,那么您可以使用functor1<animal>来迭代此类容器。在第二个版本中,模板参数将作为chimpanzee推导出来,而不是animal

  3. 如果您的类具有数据成员,则第二个变体将确保成员函数的所有特化都共享相同的数据(如果使用相同的仿函数对象)。在第一个变体中,每个特化都是一个不同的类,它有自己的数据。

答案 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}}。