template <typename T>
void foo(const T& container) {
for (auto value : container) {
// process value
}
}
foo(std::vector<int>())
foo(std::optional<int>())But I suppose in C++, given the centrality of looping constructs, this is what you would do to accommodate option.
Trying to gaslight ppl to question their reasonable reaction of std::optional transitioning from its previous behavior to an Option like behavior when no other type in C++ behaves as such is disingenuous.
Of course it is weird in the C++ context, but is it a step in the right direction? absolutely!
for (auto l : logger) {
l.log(data);
}
bent my brain for a moment. `logger` is a list of loggers to send data do? Oh, no, it's either 0 or 1 loggers.Rust's `if let` syntax maps much more closely to how I think about it. I guess if this becomes idiomatic C++ then it'd start looking perfectly normal to everyone, but it still seems odd. For instance, I don't think I could ever bring myself to write Python like this, even if it worked:
def do_something(data, logger=None):
for l in logger:
l.log(data) struct Logger;
impl Logger {
fn log(&self, _: &str) {}
}
fn do_something(data: &str, logger: Option<Logger>) {
for l in logger {
l.log(data)
}
}
fn main() {
let logger = Some(Logger);
let data = "foo";
do_something(data, logger);
}
and rustc actually warns about this: warning: for loop over an `Option`. This is more readably written as an `if let` statement
--> src/main.rs:8:14
|
8 | for l in logger {
| ^^^^^^
|
= note: `#[warn(for_loops_over_fallibles)]` on by default
help: to check pattern in a loop use `while let`
|
8 - for l in logger {
8 + while let Some(l) = logger {
|
help: consider using `if let` to clear intent
|
8 - for l in logger {
8 + if let Some(l) = logger {
|
I was actually going to say "I've never seen folks in Rust write out for loops this way, even though you can" and I suspect this lint has something to do with that!I think this is most useful in generic contexts, I agree that I would not write this exact code this way because it does feel weird, if you know you have an Option, if let is the way to go. But if you're writing code over generic iterators, it can be nice that it exists.
And to build other iterators e.g. std::iter::once is a trivial wrapper around an Option::Some.
Yeah, I don't hate it. The semantics aren't wrong, either: an Option has 0 payload items or 1. It still feels wrong to me in ways I can't fully explain.
I’m not asking to dispute. I want to be enlightened!
if (x.has_value()) {
doSomething(*x);
}