std::monostate(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

πŸ’– NAME πŸ’–

Okay bestie, this is the std::monostate(3) page from the C++ Standard Library β€” the original banner spells it C++ Standard Libary, and I’m keeping that typo energy alive 😭. The NAME is literally std::monostate - std::monostate, which is giving main-character repetition πŸ’….


✨ Synopsis ✨

Defined in header <variant>
struct monostate { };        (since C++17)

std::monostate is a unit type, fr fr β€” it’s meant to be that well-behaved empty alternative in std::variant. The iconic part: a variant of non-default-constructible types may list std::monostate as its first alternative, and that makes the variant itself default-constructible. No cap, that’s the whole slay. πŸ¦‹


πŸ› οΈ Member functions πŸ› οΈ

  • constructor β€” (implicitly declared) (public member function); it’s a trivial implicit default/copy/move constructor. Lowkey perfect.
  • destructor β€” (implicitly declared) (public member function); it’s a trivial implicit destructor.
  • operator= β€” (implicitly declared) (public member function); it’s trivial implicit copy/move assignment. Clean.

πŸ”₯ Non-member functions πŸ”₯

The crew is literally std::operator==, !=, <, <=, >, >=, <=>(std::monostate). Here’s the exact signature-and-body situation, bestie:

constexpr bool operator==( monostate, monostate )    (1) (since C++17)
noexcept { return true; }
constexpr bool operator!=( monostate, monostate )
noexcept { return false; }

constexpr bool operator< ( monostate, monostate )
noexcept { return false; }
constexpr bool operator> ( monostate, monostate )
(since C++17)
noexcept { return false; }
(until C++20)
constexpr bool operator<=( monostate, monostate )
noexcept { return true; }
                                                             (2)
constexpr bool operator>=( monostate, monostate )
noexcept { return true; }
constexpr std::strong_ordering operator<=>(
monostate, monostate ) noexcept

{
(since C++20)
    return std::strong_ordering::equal;

}

All instances of std::monostate compare equal β€” every single one, periodt. πŸ’… The page also says: the <, <=, >, >=, and != operators are synthesized from operator<=> (since C++20) and operator== respectively. That’s the tea. β˜•


🧚 Helper classes 🧚

std::hash<std::monostate> is here too:

template <>                   (since C++17)
struct std::hash<monostate>;

It specializes the std::hash algorithm for std::monostate. Obsessed with a specialized hash, honestly. πŸ“


🌈 Example 🌈

The page says // Run this code, so here’s the whole example β€” code stays code, exactly:

#include <cassert>
#include <iostream>
#include <variant>

struct S
{
    S(int i) : i(i) {}
    int i;
};

int main()
{
    // Without the monostate type this declaration will fail.
    // This is because S is not default-constructible.
    std::variant<std::monostate, S> var;
    assert(var.index() == 0);

    try
    {
        std::get<S>(var); // throws! We need to assign a value
    }
    catch(const std::bad_variant_access& e)
    {
        std::cout << e.what() << '\n';
    }

    var = 42;
    std::cout << "std::get: " << std::get<S>(var).i << '\n'
              << "std::hash: " << std::hex << std::showbase
              << std::hash<std::monostate>{}(std::monostate{}) << '\n';
}
ngl, that std::get<S>(var) line throws because we need to assign a value β€” the code comment literally says // throws! We need to assign a value 😭

Possible output:

std::get: wrong index for variant
std::get: 42
std::hash: 0xffffffffffffe19f

πŸ‘€ See also πŸ‘€

  • constructor β€” constructs the variant object (public member function). That’s the see-also link, bestie. 🫢

mwah πŸ’‹ this page came from http://cppreference.com, dated 2024.06.10, and it’s manual page std::monostate(3) β€” byeee πŸŽ€

πŸ“¦ where this page comes from