我不确定这是否是一个好主意,但是我认为你可以为std::variant
定义一个operator<<()
。
仅仅是为了好玩,我实现了下面例子中的代码(我认为它可以再简化一些):
#include <variant>
#include <iostream>
template <std::size_t I, typename T0, typename ... Ts>
std::enable_if_t<(I == 1U+sizeof...(Ts)), std::ostream &>
streamV (std::ostream & s, std::variant<T0, Ts...> const &)
{ return s; }
template <std::size_t I, typename T0, typename ... Ts>
std::enable_if_t<(I < 1U+sizeof...(Ts)), std::ostream &>
streamV (std::ostream & s, std::variant<T0, Ts...> const & v)
{ return I == v.index() ? s << std::get<I>(v) : streamV<I+1U>(s, v); }
template <typename T0, typename ... Ts>
std::ostream & operator<< (std::ostream & s,
std::variant<T0, Ts...> const & v)
{ return streamV<0U>(s, v); }
int main ()
{
std::variant<int, std::string> a, b;
a = 1;
b = "hi";
std::cout << a << b << std::endl;
}
-- 编辑 --
另一种编写streamV()
辅助函数的方式,不使用T0,Ts...
类型,而是使用std::variant_size_v
template <std::size_t I, typename V>
std::enable_if_t<(I == std::variant_size_v<V>), std::ostream &>
streamV (std::ostream & s, V const &)
{ return s; }
template <std::size_t I, typename V>
std::enable_if_t<(I < std::variant_size_v<V>), std::ostream &>
streamV (std::ostream & s, V const & v)
{ return I == v.index() ? s << std::get<I>(v) : streamV<I+1U>(s, v); }
--编辑2--
正如T.C.(感谢!)所指出的那样,我只实现了一个比std::visit()
不太有效、不太有趣和不太有用的版本 (streamV()
)。
使用std::visit()
,我的示例可以变得更加简单。
#include <variant>
#include <iostream>
template <typename T0, typename ... Ts>
std::ostream & operator<< (std::ostream & s,
std::variant<T0, Ts...> const & v)
{ std::visit([&](auto && arg){ s << arg;}, v); return s; }
int main ()
{
std::variant<int, std::string> a, b;
a = 1;
b = "hi";
std::cout << a << b << std::endl;
}
我重申一遍:这只是为了好玩,因为我认为定义operator<<()
于标准类型不是一个好主意。
我建议采用T.C.提出的解决方案,将变体实例封装到特定类中进行流操作。
std::visit([](const auto& v) { std::cout << v; }, a);
- Igor Tandetnikstd::variant
中被省略了。http://www.boost.org/doc/libs/1_65_1/doc/html/boost/operator_idp789915280.html - GManNickG