我在 https://stackoverflow.com/a/51951315/1908650 中询问了以下内容:
I want to overload
template<class T> ostream& operator<<(ostream& os, const optional<unique_ptr<T>>&
).
在评论中,@Yakk - Adam Nevraumont 指出:
The answer to that question is "you cannot". There is no good legal way to do that for a generic type T; I could explain why, but it would take a new question/answer to do so
我正在创建一个新的 Q. 来接受这个提议...
最佳答案
在与类型关联的命名空间中重载运算符的正确位置。
对于 std::optional<std::unique_ptr<T>>
有一个关联的命名空间 std
它始终存在(来自 ostream
和 optional
和 unique_ptr
),加上与 T
关联的任何命名空间.由于您要为所有类型重载,与 T
关联的 namespace 对你没有用。
在std
中引入新函数或重载是不合法的;在某些有限的情况下,您可以引入特化,但它们都不适用于此处。添加新的重载 <<
至 std
使您的程序格式错误,无需诊断。
您可以 (A) 使用装饰的 unique_ptr
或 optional
s 来自您自己的命名空间,或者 (B) 使用修饰的 ostream
, 或 (C) 编写格式化程序包装器:
namespace fmt {
template<class T>
struct wrapper_t {
T&& t;
};
template<class T>
struct is_wrapped:std::false_type{};
template<class T>
struct is_wrapped<wrapper_t<T>>:std::true_type{};
template<class OS, class T,
std::enable_if_t<!is_wrapped<OS&>{}, bool> =true
>
auto operator<<( OS& os, wrapper_t<T>&& w )
-> decltype( os << std::forward<T>(w.t) )
{ return os << std::forward<T>(w.t); }
template<class OS, class T>
auto operator<<( wrapper_t<OS&> os, T&& t )
-> decltype( os.t << std::forward<T>(t) )
{ return os.t << std::forward<T>(t); }
template<class T>
wrapper_t<T> wrap(T&& t){ return {std::forward<T>(t)}; }
}
然后 std::cout << fmt::wrap( foo )
可以找到 <<
的重载在 fmt
内, 如果没有找到调用 <<
关于包含的数据。
这也支持fmt::wrap(std::cout)
而不是包装参数。可能有错别字。
关于c++ - 为什么不能覆盖涉及第三方代码的模板类的 operator<<?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51954454/