包装Predicate Functors

时间:2011-10-12 20:38:49

标签: c++ predicate functor

我想知道关于谓词仿函数打包的约定和最佳实践。例如,给定一个类:

class Timer
{
public:
  Timer(const std::string& name, int interval);
  bool nameIs(const std::string& name) const;
private:
  std::string name_;
  int interval_;
};

TimerVec课程中使用的(在一个案例中):

class TimerVec
{
public:
  typedef std::vector<Timer>::iterator iterator;``
  <... ctors, etc ...>
  iterator findByName(const std::string& name);
private:
  std::vector<Timer> timers_;
};

并且有一个谓词函子,如:

class TimerNameIs
{
public:
  TimerNameIs(const std::string& name) : name_(name) {}
  bool operator()(const Timer& t) { return t.nameIs(name_); }
private:
  const std::string& name_;
};

我可以想到一些放置仿函数代码的地方,其中一些是:

  1. 在声明Timer
  2. 之后的头文件中
  3. 嵌套在计时器内(即所以ref变为Timer::TimerNameIs
  4. 嵌套在TimerVec(当前唯一的用户)
  5. TimerVec::findByName的实施之前的匿名命名空间中(同样是唯一使用它的地方)
  6. 虽然其中任何一个都足够了,但我更倾向于#2,但这不是我见过的。是否有任何具体的理由支持特定的选择?

2 个答案:

答案 0 :(得分:1)

我个人而言,在它自己的标题和cpp文件中。在#include "Timer.h"标头文件中使用TimerNameIs

#include "Timer.h"
#include <string>

class TimerNameIs
{
    public:
        TimerNameIs(const std::string& name) : name_(name) {}
        bool operator()(const Timer& t) { return t.nameIs(name_); }
    private:
        const std::string& name_;
};

这样做,可以将Timer和TimerNameIs从一个隔离到另一个。

答案 1 :(得分:1)

这是有争议的。我更喜欢创建一个嵌套类。这样,仅用于处理特定类型对象的仿函数在该对象中具有命名空间作用。

我通常也会为谓词match_xxx命名,其中xxx是我匹配的参数。

即便:

class Timer
{
  // ...
public:
  class match_name : public std::unary_function<Timer, bool>
  {
  public:
    match_name(const std::string& name) : name_(name) {}
    bool operator()(const Timer& t) { return t.nameIs(name_); }
  private:
    const std::string& name_;
  };
};

...因此得到利用:

std::find_if( v.begin(), v.end(), Timer::match_name("Flibbidy") );

我更喜欢这种方法,因为在{6}之后查看此代码时,Timer::match_name("Flibbidy")的语义非常清晰。

我也很谨慎从std::unary_function派生我的仿函数(尽管我上面的推导可能反转了参数)。