c – 我可以创建一个接受函数和函子作为参数的谓词吗?

我正在研究C中的一个问题,它涉及大量数据的大量子集和转换操作.为此,我创建了一个map函数和list comprehensions之类的东西.我发现我写的一堆谓词也有反转,所以我需要写:

template <typename type_t>
bool HasTenFoo(const type_t &t) {
  return t.foo >= 10.0;
}

template <typename type_t>
bool DoesntHaveTenFoo(const type_t &t) {
  return t.foo < 10.0;
}

这些都不是一个真实的例子,但它们具有代表性.我也使用了相当数量的仿函数:

class HasEnoughFoo {
public:
  HasEnoughFoo (double bar) { this->bar = bar; }
  template<typename type_t>
  bool operator()(const type_t &t) const { return t.foo >= bar; }
private:
  double bar;
};

其中一些也应该反转.我不想不必要地重复代码,而是编写一个将谓词作为参数并将返回该谓词的(反转值)的仿函数.我的拳头切成一个在下面:

/* -- Returns the opposite of some other predicate -------------------------- */

template<typename predicate_t>
class Not {
public:
  template <typename predicate_t>
  Not(predicate_t *p) { predicate = p; }

  template <typename type_t>
  bool operator()(const type_t &t) const {
    return !(*predicate)(t);
  }

private:
  predicate_t *predicate;
};

我会用以下的东西来称呼它:

new_list = old_list.subset(Not<HasEnoughFoo>(&HasEnoughFoo(10.0));

要么

new_list = old_list.subset(Not<HasTenFoo>(&HasTenFoo));

当predicate_t是像HasEnoughFoo这样的仿函数时,这似乎很有效,但是当predicate_t引用像HasTenFoo这样的常规函数​​时失败.

Visual Studio抱怨’HasTenFoo’不是参数’predicate_t’的有效模板类型参数.有没有办法编写一个可以与函子和函数一起使用的Not()谓词,或者我注定要编写几十个谓词及其反转?

最佳答案
这是你的代码工作的一个例子(我删除了foo成员,所以它只适用于双打).

template <typename type_t>
bool HasTenFoo(const type_t &t) {
  return t >= 10.0;
}

class HasEnoughFoo {
public:
  HasEnoughFoo (double bar) { this->bar = bar; }
  template<typename type_t>
  bool operator()(const type_t &t) const { return t >= bar; }
private:
  double bar;
};


template<typename predicate_t>
class Not {
public:
  Not(predicate_t p): predicate(p) { }

  template <typename type_t>
  bool operator()(const type_t &t) const {
    return !predicate(t);
  }

private:
  predicate_t predicate;
};

template <class predicate_type>
Not<predicate_type> Negate(predicate_type p)
{
    return p;
}

#include <iostream>
int main()
{
    std::cout << Negate(HasTenFoo<double>)(11.0) << '\n';
    std::cout << Negate(HasEnoughFoo(13.0))(11.0) << '\n';
}

一些重要的说明:

Not的构造函数使用初始化列表.这消除了谓词类型具有默认构造函数(HasEnoughFoo没有)的要求.

你肯定不想搞乱指向谓词的指针.功能对象应该是轻量级的对象,可以无需担心地复制.

因为Not是一个模板类,具有可能复杂的模板参数,但您通常只将其用作临时(作为获取谓词的函数的未命名参数),添加一个模板函数,为您推导出复杂类型(遍布标准库的技巧) – 这里是否定.

转载注明原文:c – 我可以创建一个接受函数和函子作为参数的谓词吗? - 代码日志