为C ++ 11算法组成多个谓词

时间:2018-10-05 01:29:56

标签: c++ c++11

我已经阅读了关于栈溢出的类似问题,例如this one。我的特定用例似乎有些不同:不是一直使用所有谓词,而是需要以不同的方式来选择和组合它们(&&,||),这取决于用户输入:我能想到的最好的例子是unix { {1}},用户可以在其中:

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

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

2 个答案:

答案 0 :(得分:1)

首先,如果像find一样,您将受到IO限制,因此可以只使用标志。不需要花哨。

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

只需编写一个模板函数即可完成所有工作,具体取决于是否设置了模板参数中的标志,然后将其从变量中的标志映射到模板参数中的标志,如下所示:

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);
}

online on coliru看到它。

答案 1 :(得分:0)

您要描述的是一棵谓词树,其中叶子是您的原子size_equal_to等,而节点是组合器(&&||)。

你有类似的东西

class Predicate
{
public:
    virtual ~Predicate();
    virtual bool operator()(Item &) = 0;
};

// child1 && child2 && ...
class Conjunction : public Predicate
{
    std::vector<std::unique_ptr<Predicate>> children;
public:
    bool operator()(Item & item)
    {
        for (auto & child : children)
            if (!(*child)(item)) 
                return false;
        return true;
    }
};

// child1 || child2 || ...
class Disjunction : public Predicate
{
    std::vector<std::unique_ptr<Predicate>> children;
public:
    bool operator()(Item & item)
    {
        for (auto & child : children)
            if ((*child)(item)) 
                return true;
        return false;
    }
};

// just inherit the operator() from a lambda
template <typename Lambda>
class Leaf : public Predicate, public Lambda 
{
    Leaf(Lambda lambda) : Lambda(lambda) {}
    using Lambda::operator();
};

然后,您将必须编写用户输入到这些Predicate对象的映射,例如解析每个参数,将参数绑定到您的size_equal_to或w / e,然后将其添加到Conjunction

如果它不是命令行输入,而是GUI,则可能需要将其绘制为具有“ And”和“ Or”节点的树状视图。