Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I write operator<< for std::variant?

Tags:

c++

I’d like to write operator<< for std::variant. The assumption will be that the operator<< for a particular variant will only be valid if operator<< is valid for all the types that the variant can contain.

like image 211
Robert Fisher Avatar asked Oct 23 '17 15:10

Robert Fisher


People also ask

What is std :: variant in C++?

class variant; (since C++17) The class template std::variant represents a type-safe union. An instance of std::variant at any given time either holds a value of one of its alternative types, or in the case of error - no value (this state is hard to achieve, see valueless_by_exception).

How do you compare STD variants?

A given instance of std::variant compares equal to another if and only if they hold the same variant alternative and said alternatives' values compare equal.

What is Monostate C++?

A monostate is a "conceptual singleton" - all data members of a monostate are static, so all instances of the monostate use the same (static) data. Applications using a monostate can create any number of instances that they desire, as each instance uses the same data.

What is boost :: variant?

Boost. Variant, part of collection of the Boost C++ Libraries. It is a safe, generic, stack-based discriminated union container, offering a simple solution for manipulating an object from a heterogeneous set of types in a uniform manner.


1 Answers

//g++ (GCC) 7.2.0
//g++ -std=c++1z -O2 -Wall -pedantic -pthread main.cpp
#include <iostream>
#include <string>
#include <variant>
#include <complex>

template<typename T, typename... Ts>
std::ostream& operator<<(std::ostream& os, const std::variant<T, Ts...>& v)
{
    std::visit([&os](auto&& arg) {
        os << arg;
    }, v);
    return os;
}

int main()
{
    using namespace std::complex_literals;
    std::variant<int, std::string, double, std::complex<double>> v = 4;
    std::cout << v << '\n';
    v = "hello";
    std::cout << v << '\n';
    v = 3.14;
    std::cout << v << '\n';
    v = 2. + 3i;
    std::cout << v << '\n';
}

Demo

This relies on passing a generic lambda to std::visit.

See this question for a problem with the previous version of this answer. This answer has been updated to avoid that problem.

like image 131
Robert Fisher Avatar answered Sep 23 '22 15:09

Robert Fisher