我在/sf/answers/3636592081/中询问了以下内容 :
我想超载
template<class T> ostream& operator<<(ostream& os, const optional<unique_ptr<T>>&
).
在评论中,@ Yakk - Adam Nevraumont指出:
这个问题的答案是"你做不到".对于通用类型T,没有合法的方法可以做到这一点; 我可以解释原因,但这样做会有新的问题/答案
我正在创造一个新的Q.以接受这种报价......
在与类型关联的命名空间中重载运算符的适当位置.
对于std::optional<std::unique_ptr<T>>
有一个关联的命名空间std
是永远存在的(从ostream
和optional
和unique_ptr
),加上无论命名空间相关联T
.由于您希望为所有类型重载,因此与之关联的命名空间T
对您无用.
引入新功能或过载是不合法的std
; 在某些有限的情况下,您可以引入专业化,但这些都不适用于此.添加一个新的过载<<
,以std
使你的程序生病形成,没有诊断需要.
您可以(A)使用自己的命名空间中的deco 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)}; }
}
Run Code Online (Sandbox Code Playgroud)
然后std::cout << fmt::wrap( foo )
可以找到的过载<<
范围内fmt
,如果没有找到调用<<
上所包含的数据.
这也支持fmt::wrap(std::cout)
而不是包装参数.可能有错别字.