Predicates

本文深入探讨了STL算法中常见的陷阱之一,并提供了使用lambda表达式来优化代码的方法,避免了状态依赖的问题,确保算法的正确性和效率。

Gotchas (Effective STL also mentions this gotcha):

1) Predicates should be always stateless.
2) The operator() member function should be always const


class Nth { // function object that returns true for the nth call
private:
    int nth; // call for which to return true
    int count; // call counter
public:
    Nth (int n) : nth(n), count(0) {  // having state indicates problem
    }
    bool operator() (int) {  // non-const member operation() function indicates problem
        return ++count == nth;
    }
};

list<int> coll = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
list<int>::iterator pos;
pos = remove_if(coll.begin(),coll.end(), // range
Nth(3)); // remove criterion
coll.erase(pos,coll.end());

// May have other output depending on the STL implementation.
Output: 1 2 4 5 7 8 9 10

Root cause:
The algorithm uses find_if() to find the first element that should be removed. However, the
algorithm then uses a copy of the passed predicate op to process the remaining elements, if any.
Here, Nth in its original state is used again and also removes the third element of the remaining
elements, which is in fact the sixth element.

template <typename ForwIter, typename Predicate>
ForwIter std::remove_if(ForwIter beg, ForwIter end, Predicate op)
{
    beg = find_if(beg, end, op);  // find_if takes a copy of 'op'
    if (beg == end) {
        return beg;
    }
    else {
        ForwIter next = beg;
        return remove_copy_if(++next, end, beg, op);  // here 'op' still have the original state.
    }
}

Solution: Use lambdas
int count=0; // call counter
pos = remove_if(coll.begin(),coll.end(),   [&count] (int) {
                                                                        return ++count == 3;
                                                                    });

### 谓词逻辑在编程中的应用 #### 编程中的谓词逻辑概念 谓词逻辑是一种形式化表示方法,用于描述对象及其属性之间的关系。在计算机科学领域内,特别是在数据库查询语言(SQL)以及某些高级编程范式中,谓词被广泛应用于表达条件判断和筛选标准。 对于SQL查询而言,`WHERE`子句后面跟的就是所谓的“谓词”。这些谓词定义了哪些记录应该被选中作为查询的结果集的一部分[^1]。例如,在一个简单的SELECT语句中: ```sql SELECT * FROM employees WHERE salary > 50000; ``` 这里的 `salary > 50000` 就是一个典型的谓词语法结构,它指定了只返回那些薪水超过五万美元的员工信息。 除了基本的关系运算符外(如=、<、>),还可以组合多个简单谓词形成复杂条件来满足更精细的数据检索需求。这可以通过使用AND、OR等逻辑操作符实现,并且可以嵌套多层括号以控制优先级顺序[^2]。 #### Hibernate框架下的动态查询构建器 当涉及到面向对象的应用程序开发时,像Hibernate这样的ORM(Object Relational Mapping)工具提供了更加优雅的方式来创建基于谓词的查询。通过Criteria API 或者 JPA Criteria Query接口,开发者能够利用Java代码编写灵活而强大的查询逻辑而不必直接书写原始SQL字符串,从而提高了可读性和安全性的同时减少了潜在错误的发生几率。 下面给出一段采用JPA Criteria API编写的示例代码片段,展示了如何在一个实体类上设置复杂的谓词条件来进行数据查找: ```java // 假设有一个Employee实体映射到employees表 EntityManager em = ... ; // 获取 EntityManager 实例 CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Employee> cq = cb.createQuery(Employee.class); Root<Employee> employee = cq.from(Employee.class); Predicate predicateLastName = cb.equal(employee.get("lastName"), "Smith"); Predicate predicateSalaryHigh = cb.greaterThan(employee.<BigDecimal>get("salary"), new BigDecimal(70000)); cq.where(cb.and(predicateLastName, predicateSalaryHigh)); List<Employee> result = em.createQuery(cq).getResultList(); ``` 这段代码首先建立了两个单独的谓词——一个是针对姓氏等于'Smith'的情况;另一个则是工资高于七万美金的情形。接着这两个谓词通过逻辑与(`and`)连接起来构成最终的选择条件并执行查询。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值