c++ - 为什么不能覆盖涉及第三方代码的模板类的 operator<<?

标签 c++ overloading

我在 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它始终存在(来自 ostreamoptionalunique_ptr ),加上与 T 关联的任何命名空间.由于您要为所有类型重载,与 T 关联的 namespace 对你没有用。

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

您可以 (A) 使用装饰的 unique_ptroptional 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/

相关文章:

c++ - 在异构元组上映射 C++ 重载函数?

c# - 如何使用自定义类型重载 System.Math 方法

c++ - 在 C++ 中复制 Haskell 的返回类型重载(通过类型类)

c++ - 请帮助我理解这种语法(在 C++ 中实现静态断言)

c++ - Relation和大多数Merge Operation的计算?

c++ - 从规范的 CPPunit 测试用例中生成引用测试文件

c++ - 如何添加到 QtConcurrent::map 操作的 QStringList 中?

c++ - 我应该怎么做而不是函数模板的部分特化?

c++ - 重载函数中的静态变量

c++ - 如何在没有 boost::timer 的情况下以毫秒为单位计时