首页 > 解决方案 > 为 C++11 算法组合多个谓词

问题描述

我已经阅读过关于 stackoverflow 的类似问题,例如这个。我的特定用例似乎有点不同:我不需要一直应用所有谓词,而是需要以不同的方式选择和组合它们(&&,||),等待用户输入:我能想到的一个最好的例子是 unix find,用户可以:

# find all files on condition:
# size more than 100K, modified 7 days ago, from user group abc 
find /path/to/somewhere -type f -size +100K -mtime +7 -group abc

假设我定义了以下谓词:

bool size_equal_to() { ... }
bool size_greater_to() { ... }
bool size_less_than() { ... }
bool type_is_file() { ... }
bool type_is_dir() { ... }
bool mtime_plus() { ... }

将 lambda 函数中的此类谓词组合到容器列表(如前面的问题所建议的那样)是可行的,但代码结构非常混乱。有什么更好的建议吗?

标签: c++c++11

解决方案


好吧,首先,如果它像 find,你是 IO-bounded,所以你可以只使用标志。没必要花里胡哨。

但是现在让我们假设您实际上是计算受限的,并且测试标志很重要:

只需编写一个模板函数,根据是否设置了模板参数中的标志来执行所有操作,然后从变量中的标志映射到模板参数中的标志,如下所示:

class Task {
    ... Whatever
public:
    template <std::size_t N>
    void operator()(std::integral_constant<std::size_t, N>) {
        if (N & 1) test_0();
        if (N & 2) test_1();
        if (N & 4) test_2();
        ...
    }
}

my_mux<1<<6>(n, the_task);

当然,你还需要my_mux()

#include <type_traits>
#include <stdexcept>
namespace detail {
    template <std::size_t N, class F>
    typename std::enable_if<!N>::type my_mux_helper(std::size_t n, F& f) {
        n == 0 ? f(std::integral_constant<std::size_t, N>()) : throw std::invalid_argument("n must be smaller than N");
    }
    template <std::size_t N, class F>
    typename std::enable_if<N>::type my_mux_helper(std::size_t n, F& f) {
        n == N ? f(std::integral_constant<std::size_t, N>()) : my_mux_helper<N - 1>(n, f);
    }
}

template <std::size_t N, class F>
void my_mux(std::size_t n, F f) {
    detail::my_mux_helper<N - 1>(n, f);
}

在 coliru 上在线查看。


推荐阅读