为什么不能覆盖 operator<<;对于涉及第三方代码的模板类? [英] Why is it not possible to override operator&lt;&lt; for template classes involving third-party code?

查看:40
本文介绍了为什么不能覆盖 operator<<;对于涉及第三方代码的模板类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 https://stackoverflow.com/a/51951315/1908650 中询问了以下内容:

I asked about the following in https://stackoverflow.com/a/51951315/1908650 :

我想重载templateostream&运算符<<(ostream& os, const optional>&).

在评论中,@Yakk - Adam Nevraumont 指出:

In the comments, @Yakk - Adam Nevraumont notes:

这个问题的答案是你不能".对于泛型类型 T,没有好的合法方法可以做到这一点;我可以解释原因,但这样做需要一个新的问题/答案

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. 以接受友好的提议...

I'm creating a new Q. to take up the kind offer...

推荐答案

在与类型关联的命名空间中重载运算符的正确位置.

The proper place to overload operators in in the namespace associated with the type.

对于 std::optional<std::unique_ptr<T>>,有一个关联的命名空间 std 始终存在(来自 ostreamoptionalunique_ptr),以及与 T 关联的任何命名空间.由于您想为所有类型重载,与 T 关联的命名空间对您没有用.

For std::optional<std::unique_ptr<T>> there is one associated namespace std that is always there (from ostream and optional and unique_ptr), plus whatever namespace is associated with T. As you want to overload for all types, the namespace(s) associated with T are not useful to you.

std中引入新函数或重载是不合法的;在某些有限的情况下,您可以引入专业化,但它们都不适用于此处.将 << 的新重载添加到 std 会使您的程序格式错误,无需诊断.

It is not legal to introduce a new function or overload into std; in certain limited circumstances you can introduce specializations, but none of them apply here. Adding a new overload of << to std makes your program ill formed, no diagnostic required.

您可以 (A) 使用装饰的 unique_ptroptional 来自您自己的命名空间,或 (B) 使用装饰的 ostream,或(C) 编写格式化程序包装器:

You could (A) use decorated unique_ptr or optionals from your own namespace, or (B) use a decorated ostream, or (C) write a formatter wrapper:

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 中找到 << 的重载,如果没有找到则调用 << 包含的数据.

then std::cout << fmt::wrap( foo ) can find overloads of << within fmt, and if none are found invokes << on the contained data.

这也支持 fmt::wrap(std::cout) 而不是包装参数.可能有错别字.

This also supports fmt::wrap(std::cout) instead of wrapping the arguments. There are probably typos.

这篇关于为什么不能覆盖 operator<<;对于涉及第三方代码的模板类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆