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.
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).
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.
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.
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.
//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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With