简体   繁体   English

迭代 std::optional

[英]Iterating over std::optional

I tried to iterate over an std::optional :我试图迭代一个std::optional

for (auto x : optionalValue)
{
    ...
}

With the expectation of it doing nothing if optionalValue is empty but doing one iteration if there is a value within, like it would work in Haskell (which arguably made std::optional trendy):如果optionalValue为空,则期望它什么也不做,但如果其中有一个值,则执行一次迭代,就像它在 Haskell 中工作一样(可以说这使std::optional成为时尚):

forM optionalValue
( \x ->
    ...
)

Why can't I iterate an optional?为什么我不能迭代一个可选项? Is there another more standard C++ method to do this?是否有另一种更标准的 C++ 方法来执行此操作?

std::optional does not have a begin() and end() pair. std::optional没有begin()end()对。 So you cannot range-based-for over it.因此,您不能对其进行基于范围的处理。 Instead just use an if conditional.相反,只需使用if条件。

See Alternative 2 for the closest thing to what you want to do.请参阅备选方案 2,了解与您想要做的最接近的事情。

Edit: If you have a temporary from a call result you don't have to check it explicitly:编辑:如果你有一个临时的呼叫结果,你不必明确地检查它:

if (auto const opt = function_call()) {
  do_smth(*opt);
}

The check for static_cast<bool>(opt) is done implicitly by if . static_cast<bool>(opt)的检查由if隐式完成。


Alternative 1备选方案 1

Another alternative is to not use an std::optional<T> but std::variant<std::monostate, T> .另一种选择是不使用std::optional<T>而是使用std::variant<std::monostate, T> You can then either use the overloaded idiom or create a custom type to handle the monostate:然后,您可以使用overloaded的习惯用法或创建自定义类型来处理单态:

template <typename F>
struct MaybeDo {
  F f;

  void operator()(std::monostate) const {}
  template <typename T>
  void operator()(T const& t) const { f(t); }
};

which will allow you to visit the value with some function:这将允许您使用某些功能访问该值:

std::variant<std::monostate, int> const opt = 7;
std::visit(MaybeDo{[](int i) { std::cout << i << "\n"; }}, opt);

Alternative 2备选方案 2

You can also wrap optional in a thing that allows you to iterate over it.您还可以将 optional 包装在允许您对其进行迭代的事物中。 Idea:主意:

template <typename T>
struct IterateOpt {
  std::optional<T> const& opt;
  
  struct It {
    std::optional<T> const* p;
    It& operator++() {
      p = nullptr;
      return *this;
    }
    It operator++(int) {
      return It{nullptr};
    }
    auto const& operator*() const { **p; }
  };
  auto begin() const {
    if (opt) return It{&opt};
    else end();
  }
  auto end() const {
    return It{nullptr};
  }
};

This is a crude sketch of how to do this and probably requires some love to work on different situations (like a non-const optional).这是如何做到这一点的粗略草图,可能需要一些爱来处理不同的情况(比如非常量可选)。

You can use this to "iterate" over the optional:您可以使用它来“迭代”可选:

for (auto const& v: IterateOpt{function_call()}) {
  do_smth(v);
)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM