【发布时间】:2019-01-12 16:47:47
【问题描述】:
是否可以以惰性方式评估 std::optional::value_or(expr) 参数,所以 expr 仅在没有值的情况下计算?
如果不是,什么是合适的替代品?
【问题讨论】:
标签: c++ stl c++17 stdoptional
是否可以以惰性方式评估 std::optional::value_or(expr) 参数,所以 expr 仅在没有值的情况下计算?
如果不是,什么是合适的替代品?
【问题讨论】:
标签: c++ stl c++17 stdoptional
你可以编写你的辅助函数:
template<typename T, typename F>
T lazy_value_or(const std::optional<T> &opt, F fn) {
if(opt) return opt.value();
return fn();
}
然后可以用作:
T t = lazy_value_or(opt, [] { return expensive_computation();});
如果这比显式输入要少得多,那由您来判断;不过,您可以使用宏使其更短:
#define LAZY_VALUE_OR(opt, expr) \
lazy_value_or((opt), [&] { return (expr);})
用作
T t = LAZY_VALUE_OR(opt, expensive_calculation());
这与我认为你想要的最接近,但可能会因为它隐藏了太多东西而令人不悦。
【讨论】:
goto 一样,宏是一种工具,并且在现代 C++ 中也占有一席之地;在法庭上妖魔化他们,至于任何“绝对”的判断,都是错误的和短视的。这种情况有点边缘,因为它隐藏了很多东西(我什至警告过这一点),但这取决于 OP 来判断。
value_or_else。
#include <optional>
template <typename F>
struct Lazy
{
F f;
operator decltype(f())() const
{
return f();
}
};
template <typename F>
Lazy(F f) -> Lazy<F>;
int main()
{
std::optional<int> o;
int i = o.value_or(Lazy{[]{return 0;}});
}
【讨论】:
template <typename F> Lazy(F f) -> Lazy<F>; 是什么样的构造?它看起来像一个带有尾随返回类型的函数模板的前向声明,但它不是......
operator decltype(auto)() const 是更好的 IMO(更少的括号)。 :)
operator invoke_result_t<F>()
选择函数类型。
然后可以传入一个 lambda,调用它时会在请求的时刻计算正确的值。
std::optional<std::function<int()>> opt;
int a = 42;
opt = [=] { return a; }
int b = 4;
int c = opt.value_or([=] { return b * 10 + 2;}) ();
【讨论】: