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 库,我可能会用它来增强 optionalvector 输出,但是我想避免重新发明轮子。

因此,基本思想是添加一个模板化的 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,这甚至适用于原始指针。不包括 variantvector,尽管添加起来也不难。

要处理 std::variantstd::tuplestd::pair,您可能会做同样的事情,只是使用 std::get<X> 而不是 operator*