我已经阅读了关于栈溢出的类似问题,例如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函数中将这样的谓词集合组成容器列表(如先前的问题所建议)是可行的,但是代码结构非常混乱。有什么更好的建议吗?
答案 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”节点的树状视图。