【发布时间】:2021-05-13 12:14:39
【问题描述】:
前言
我问a similar 问题:假设我有一个谓词auto p1 = [](int x){ return x > 2; } 和一个谓词auto p2 = [](int x){ return x < 6; },我如何结合p1 和p2 得到p1and2 这样p1and2(x) == p1(x) && p2(x)?答案是使用boost::hana::demux(有关详细信息,请参阅链接的问题)。
新问题和问题
然而,有时,只有当另一个谓词评估为给定的真实性值时,才应该对一个谓词进行评估,例如true.
例如,一个谓词可能是
constexpr auto has_value = [](std::optional<int> opt){ return opt.has_value(); };
和其他谓词
constexpr auto has_positive = [](std::optional<int> opt){ return opt.value() == 3; };
以下内容很容易识别
bool b1 = has_value(some_opt_int) && has_positive(some_opt_int); // true or false, but just fine either way
bool b2 = has_positive(some_opt_int) && has_value(some_opt_int); // runtime error if !some_opt_int.has_value()
定义
constexpr auto all = boost::hana::demux([](auto const&... x) { return (x && ...); });
并像这样使用它
std::optional<int> empty{};
contexpr auto has_value_which_is_positive = all(has_value, has_positive);
bool result = has_value_which_is_positive(empty);
所以我的问题是,我如何结合has_value 和has_positive 得到has_value_which_is_positive?更一般地说,我如何将几个谓词“和”在一起,以便仅在短路机制所需的范围内对它们进行评估?
我的尝试
我认为,为了防止谓词被评估,我可以将它们包装在一些函数对象中,当应用于参数(std::optional)时,返回另一个包装谓词和std::optional 在一起,并且有一个 operator bool 转换函数,只有在计算折叠表达式时才会触发。
这是我的尝试,这是可悲的未定义行为,因为main 中的断言有时会失败,有时不会:
#include <optional>
#include <boost/hana/functional/demux.hpp>
#include <boost/hana/functional/curry.hpp>
template<typename P, typename T>
struct LazilyAppliedPred {
LazilyAppliedPred(P const& p, T const& t)
: p(p)
, t(t)
{}
P const& p;
T const& t;
operator bool() const {
return p(t);
}
};
constexpr auto lazily_applied_pred = [](auto const& p, auto const& t) {
return LazilyAppliedPred(p,t);
};
auto constexpr lazily_applied_pred_curried = boost::hana::curry<2>(lazily_applied_pred);
constexpr auto all_true = [](auto const&... x) { return (x && ...); };
constexpr auto all = boost::hana::demux(all_true);
constexpr auto has_value = [](std::optional<int> o){
return o.has_value();
};
constexpr auto has_positive = [](std::optional<int> o){
assert(o.has_value());
return o.value() > 0;
};
int main() {
assert(all(lazily_applied_pred_curried(has_value),
lazily_applied_pred_curried(has_positive))(std::optional<int>{2}));
}
【问题讨论】:
标签: c++ functional-programming lazy-evaluation short-circuiting boost-hana