top | item 45598236

(no title)

mk12 | 4 months ago

Would you ever really use that? That just shows how bad it is, IMO. Any time I want a sum type I want names, not hardcoded integers.

discuss

order

loeg|4 months ago

I wouldn't use it (in any language), but the claim was that it is impossible. It isn't.

Maxatar|4 months ago

I treat std::variant the same way I treat std::tuple, which is that I use them internally/privately and don't expose them as part of a public API.

If I want to expose a std::variant publicly then I take the effort to emulate Rust, which I think everyone agrees has an incredibly useful and elegant enum type so it looks like this:

    int main() {
      auto s1 = ConnectionState::Disconnected();
      auto s2 = ConnectionState::Connecting(3);
      auto s3 = ConnectionState::Connected("192.168.1.5", 8080);

      for (const auto& state : {s1, s2, s3}) {
        state.visit(
          [](Disconnected) {
            std::cout << "Disconnected\n";
          },
          [](int retries) {
            std::cout << "Connecting (" << retries << " retries)\n";
          },
          [](const IpAddress& ip) {
            std::cout << "Connected to " << ip.host << ":" << ip.port << "\n";
          });
      }
    }
To implement that I currently do need to write out boilerplate like below, but with C++26 I will be able to use the upcoming reflection feature to automatically implement the bulk of this code by reflecting on the std::variant directly:

    class ConnectionState : private std::variant<std::monostate, int, IpAddress> {
      public:
        static auto Disconnected() { return ConnectionState(std::monostate{}); }
        static auto Connecting(int retries) { return ConnectionState(retries); }
        static auto Connected(std::string host, uint16_t port) {
          return ConnectionState(IpAddress{std::move(host), port});
        }

        template <typename... Fs>
        decltype(auto) visit(Fs&&... fs) const {
          auto visitor = Overload{std::forward<Fs>(fs)...};
          return std::visit(visitor, *this);
        }

      private:
        using std::variant<std::monostate, int, IpAddress>::variant;
    };

    using Disconnected = std::monostate;
...