>
printfprintf is a good, easy example of a case where you need to have different logic depending on which variant you are. It's not an endorsement of printf qua printf over cout qua cout. cout only works here because the standard library has already overloaded cout for each variant, as the author ends up doing. If you were doing anything else, you'd need either the explicit overloading or the if-constexpr thing.
The example from the Rust book (which, full disclosure, I wrote because I <3 tagged enums and pattern-matching and the previous examples weren't that great) is probably a better one: https://doc.rust-lang.org/book/first-edition/enums.html
enum Message {
Quit,
ChangeColor(i32, i32, i32),
Move { x: i32, y: i32 },
Write(String),
}
For these four variants, your behavior is very different. What you want to be able to write is something like
loop {
match get_message() {
Message::Quit => {
return;
}
Message::ChangeColor(r, g, b) => {
print!("\027[38;2;{};{};{}m", r, g, b);
}
Message::Move {x: column, y: row} => {
print!("\027[{};{}H", row, column);
}
Message::Write(str) => {
print!("{}", &str);
}
}
}
which (modulo any errors from me not actually testing this) is perfectly valid Rust code, that's entirely readable even if you only know C++ and not Rust. As far as I know, you can't write anything anywhere as straightforward as this in C++. You'd need to define at least two new classes, probably four, for the four variants, plus another function that's overloaded on the four classes to handle the behaviors; you can't have the behavior be inline in your existing function, as above. (The way I wrote this, it's just using the global print function, but it'd rapidly get messy if you needed to pass a reference to a console object or whatever.) Alternatively, you would in fact need the constexpr trickery the article suggests, which would let you write it inline with some lambdas. None of this is needed in a language with language-level support for tagged unions and pattern matching (of which Rust is hardly the only one - please don't take this as advocacy of Rust in particular); you can just write normal control structures as above.
Alternatively, none of this is needed in a language with dynamic typing; you'd just do
while True:
msg = get_msg()
if msg.type == "Quit":
return
elif msg.type == "ChangeColor":
print "027[38;2;{};{};{}m".format(msg.r, msg.g, msg.b)
...
but presumably you're using C++ because you want to be able to do this without that level of dynamism (which puts some unenviable lower bounds on efficiency).