Hacker News new | past | comments | ask | show | jobs | submit login

Parton my naiveté, but if you wanted a value that's either a thing, or not-a-thing, why wouldn't you express that with a std::optional? What advantage does std::monostate have versus option types?

Brevity, I guess? I suppose the most brief way to express absence or presence of value in C++ is a pointer, but I could be tried at the Hague for that take.

None of this is to be facetious, I'm really trying to learn here. I'm not a C++ guy by trade. C and Rust are my day-to-day languages.




You're not wrong, if you just want "a T or nothing", optional is the way to go. But what if you want "a T, a U, a V, or nothing"? Then you do

    std::variant<std::monostate, T, U, V>
Or

    std::optional<std::variant<T, U, V>>
But then the "none" state is a bit more "special", it's not just one of the options. The sizeof of the type will also probably be a bit bigger, because it has to contain both the bool for the optional, as well as the tag for the variant.

The other obvious use is what the article states, that it allows the variant to be default constructed even if none of its members are. Though you can do that with optional as well. It's mostly a matter of style. I mostly avoid std::monostate because the name is so confusing, I really agree with the other users that something like std::unit or std::none would be better.


> it allows the variant to be default constructed even if none of its members are

Ah, okay! So it's serving the same purpose as the "None" in this Rust snippet:

    enum Foo {
        None, // <-- impl core::Default and return this
        T(T),
        U(U),
        V(V),
    }
That makes sense, though it really shows how the legacy of C++'s type system limits stdlib design in the present day. It'd be awfully nice to be able to just write std::variant<void, T, U, V>.


Exactly. The difference here is that std::variant doesn’t “name” the options, you just get the type (and an index, so variant can contain duplicate types). So you have to have some marker type that’s like “this contains nothing”.

Fundamentally, Rust’s enums are a much better way of doing this thing compared to std::variant, but C++ did the best it could without changing the core language. Which arguably they should have done.


I mean, it's very trivial to make your own basic wrapper with "void" in the API if that's what you want: https://gcc.godbolt.org/z/v6EPTaaPY


I suppose that code is "trivial" in the same sense that anything else involving C++11 is "trivial."


this took like less than 5 minutes to write, this is definitely in the "trivial" realm




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: