std :: optional :: value_or() - 懒惰参数评估

vtr*_*trz 15 c++ stl c++17 stdoptional

是否有可能以std::optional::value_or(expr)懒惰的方式评估参数,所以expr仅在没有值的情况下计算?

如果没有,什么是适当的替代品?

Pio*_*cki 23

#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;}});
}
Run Code Online (Sandbox Code Playgroud)

DEMO

  • @BenVoigt这是一个模板演绎指南 (6认同)
  • 什么样的构造是`template <typename F> Lazy(F f) - > Lazy <F>;`?它看起来像一个具有尾随返回类型的函数模板的前向声明,但它不是...... (2认同)
  • `operator decltype(auto)()const`是更好的IMO(更少的parens).:) (2认同)
  • @Rakete1111天啊,这打破了我的大脑......"嘿,这是转换......嗯......好吧,我们会看到!" (2认同)
  • @Rakete1111还有`operator invoke_result_t&lt;F&gt;()` (2认同)

Mat*_*lia 9

您可以编写辅助函数:

template<typename T, typename F>
T lazy_value_or(const std::optional<T> &opt, F fn) {
    if(opt) return opt.value();
    return fn();
}
Run Code Online (Sandbox Code Playgroud)

然后可以用作:

T t = lazy_value_or(opt, [] { return expensive_computation();});
Run Code Online (Sandbox Code Playgroud)

如果这明显少于明确的打字,那么由你来判断; 仍然,你可以用宏来缩短它:

#define LAZY_VALUE_OR(opt, expr) \
    lazy_value_or((opt), [&] { return (expr);})
Run Code Online (Sandbox Code Playgroud)

用作

T t = LAZY_VALUE_OR(opt, expensive_calculation());
Run Code Online (Sandbox Code Playgroud)

这是我认为你想要的最接近的,但可能会因为它隐藏了太多东西而感到不满.

  • @JesperJuhl就像`goto`,即使在现代C++中,宏也是一种工具并且占有一席之地; 如同任何"绝对"的判断一样,妖魔化他们对法庭,是错误和短视的.这种情况有点边缘,因为它隐藏了很多东西(我甚至警告过这个),但这取决于OP来判断. (14认同)
  • "你可以用一些宏来缓解这个问题" - 请不要提倡使用宏. (2认同)
  • 当然,它们是工具箱中的工具.他们有自己的用途.但是,我认为我们不应该提倡使用它们,因为*大多数*使用宏是坏的或不合适的 - *大多数*事情可以在不使用宏的情况下更好地完成.是的,他们存在.他们有目的.除非他们是最后一个*唯一*度假村(恕我直言),否则不要提及它们. (2认同)