X 的 ostream,然后生成 optional<X>、unique_ptr<X>、shared_ptr<X>,可能是 variant<X, Z> 或 vector<X>
ostream for X, then generate for optional<X>, unique_ptr<X>, shared_ptr<X>, possibly variant<X, Z> or vector<X>
给定一个应该打印的类型 X
我自然会实现
std::ostream& operator<<(std::ostream& os, const X& x);
如果我想避免对 std::optional<X>
、std::unique_ptr<X>
、std::shared_ptr<X>
等各种包装器重复工作,我有什么选择?是否已经有实现此功能的库?考虑到这些关键字,像这样的东西很难搜索,我能找到的封闭库是 Compile Time Type Information 库,我可能会用它来增强 optional
和 vector
输出,但是我想避免重新发明轮子。
因此,基本思想是添加一个模板化的 operator<<
,它会根据传递的对象的 return 类型 operator*
离开 SFINAE。像这样:
template <typename T, typename Expected>
using deref_to = std::is_same<std::decay_t<decltype(*std::declval<T>())>, Expected>;
template <typename T, typename = std::enable_if_t<deref_to<T, X>::value>>
std::ostream& operator<<(std::ostream &os, const T &foo) {
if(!foo)
os << "{}";
else
os << *foo;
return os;
}
Live demo,这甚至适用于原始指针。不包括 variant
或 vector
,尽管添加起来也不难。
要处理 std::variant
、std::tuple
和 std::pair
,您可能会做同样的事情,只是使用 std::get<X>
而不是 operator*
。
给定一个应该打印的类型 X
我自然会实现
std::ostream& operator<<(std::ostream& os, const X& x);
如果我想避免对 std::optional<X>
、std::unique_ptr<X>
、std::shared_ptr<X>
等各种包装器重复工作,我有什么选择?是否已经有实现此功能的库?考虑到这些关键字,像这样的东西很难搜索,我能找到的封闭库是 Compile Time Type Information 库,我可能会用它来增强 optional
和 vector
输出,但是我想避免重新发明轮子。
因此,基本思想是添加一个模板化的 operator<<
,它会根据传递的对象的 return 类型 operator*
离开 SFINAE。像这样:
template <typename T, typename Expected>
using deref_to = std::is_same<std::decay_t<decltype(*std::declval<T>())>, Expected>;
template <typename T, typename = std::enable_if_t<deref_to<T, X>::value>>
std::ostream& operator<<(std::ostream &os, const T &foo) {
if(!foo)
os << "{}";
else
os << *foo;
return os;
}
Live demo,这甚至适用于原始指针。不包括 variant
或 vector
,尽管添加起来也不难。
要处理 std::variant
、std::tuple
和 std::pair
,您可能会做同样的事情,只是使用 std::get<X>
而不是 operator*
。