是否有可能以一种懒加载的方式评估std::optional::value_or(expr)
参数,以便只在没有值的情况下计算expr
?
如果不行,那么适当的替换是什么?
是否有可能以一种懒加载的方式评估std::optional::value_or(expr)
参数,以便只在没有值的情况下计算expr
?
如果不行,那么适当的替换是什么?
#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 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 的判断。 - Matteo Italiavalue_or_else
。 - Barrystd::optional<std::function<int()>> opt;
int a = 42;
opt = [=] { return a; }
int b = 4;
int c = opt.value_or([=] { return b * 10 + 2;}) ();
template <typename F> Lazy(F f) -> Lazy<F>;
这是什么样的结构?它看起来像一个带有尾返回类型的函数模板的前向声明,但实际上不是... - Ben Voigtoperator decltype(auto)() const
更好(少用括号)。 :) - Rakete1111operator invoke_result_t<F>()
。 - Barry