我正在研究C++中的一个问题,它涉及大量数据的大量子集和转换操作.为此,我创建了一个map函数和list comprehensions之类的东西.我发现我写的一堆谓词也有反转,所以我需要写:
template <typename type_t>
bool HasTenFoo(const type_t &t) {
return t.foo >= 10.0;
}
Run Code Online (Sandbox Code Playgroud)
和
template <typename type_t>
bool DoesntHaveTenFoo(const type_t &t) {
return t.foo < 10.0;
}
Run Code Online (Sandbox Code Playgroud)
这些都不是一个真实的例子,但它们具有代表性.我也使用了相当数量的仿函数:
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;
};
Run Code Online (Sandbox Code Playgroud)
其中一些也应该反转.我不想不必要地重复代码,而是编写一个将谓词作为参数并将返回该谓词的(反转值)的仿函数.我的拳头切成一个在下面:
/* -- 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;
};
Run Code Online (Sandbox Code Playgroud)
我会用以下的东西来称呼它:
new_list = old_list.subset(Not<HasEnoughFoo>(&HasEnoughFoo(10.0));
Run Code Online (Sandbox Code Playgroud)
要么
new_list = old_list.subset(Not<HasTenFoo>(&HasTenFoo));
Run Code Online (Sandbox Code Playgroud)
这似乎predicate_t是一个类似的函子HasEnoughFoo,但是在predicate_t引用常规函数时失败了HasTenFoo.
Visual Studio抱怨说'HasTenFoo' is not a valid template type argument for parameter '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';
}
Run Code Online (Sandbox Code Playgroud)
一些重要的说明:
Not的构造函数使用初始化列表.这消除了谓词类型具有默认构造函数(HasEnoughFoo没有)的要求.
你肯定不想搞乱指向谓词的指针.功能对象应该是轻量级的对象,可以无需担心地复制.
由于并非是一个模板类,有可能引起复杂的模板参数,但你通常只是用它作为临时(不具名参数取谓词的函数),添加推导出复杂的类型,你的模板函数(在整个标准库中使用的技巧) - 这里Negate.