是否可以定义 operator<<对于模板类型? [英] Is it possible to define operator&lt;&lt; for templated types?

查看:28
本文介绍了是否可以定义 operator<<对于模板类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想打印 STL 类型的值,例如 std::maps,例如:

I want to print values of STL types like std::maps, for example:

int main()
{
    std::map<int, std::vector<int>> t = {{1, {2, 3}}, {4, {5}}};
    std::cout << t << std::endl;
    return 0;
}

这失败了,因为 operator<< 没有为这些类型定义.

This fails because operator<< isn't defined for these types.

如果我尝试自己定义它,我还必须转发声明我的定义,否则编译失败:

If I try to define it myself, I have to also forward declare my definitions, otherwise the compilation fails with:

error: call to function 'operator<<' that is neither visible in the template definition nor found by argument-dependent lookup
        o << sep << "{" << x.first << ", " << x.second << "}";
...
note: 'operator<<' should be declared prior to the call site std::ostream& operator<< (std::ostream& o, const std::vector<T>& vec)

这很不幸,因为必须前向声明方法需要为每种类型使用两个包含(先前向声明,然后是实现).

That is unfortunate because having to forward declare the methods would require using two includes for each type (forward declarations first and then implementations).

  • 有没有办法以模块化的方式为模板类型定义 operator<<?
  • 这种困难是否是 operator<<< 不可用于开箱即用的 STL 类型的原因?
  • Is there a way to define operator<< for templated types in a modular way?
  • Is this difficulty the reasoning behind why operator<< isn't available for STL types out of the box?

参考:带有前向声明的工作实现

推荐答案

在你的要点中,operator<< 重载 std::mapstd::vector 的重载之前定义.

In your gist, the operator<< overload for std::map<K, V> is defined before the overload for std::vector<T>.

GCC 很乐意接受您的代码而不会引发任何错误,而 Clang(我猜是您正在使用的那个)完全拒绝使用您发布的消息编译它,这基本上表明没有好的 operator<std::vector 尚未定义.

GCC gladly accepts your code it without raising any errors, while Clang (the one you are using I guess) outright refuses to compile it with the message you have posted, which basically says that that there's no good operator<< for std::vector<T> has been defined yet.

我应该仔细检查标准在这种情况下的规定,但我的第一印象是 GCC 正在接受您的代码,因为 operator<<(ostream&,const std::vector<T>&) 在实例化时定义(发生在 main() 中,当您调用 std::cout << t 时),而 Clang 严格认为是可见的仅定义模板时已知的那些函数.

I should double check what the standard specifies in this situations, but my first impression is that GCC is accepting your code because operator<<(ostream&,const std::vector<T>&) is defined at instantiation time (which happens in main(), when you call std::cout << t), while Clang strictly considers as visible only those functions that are known at the time the template has been defined.

如果你为 operator<<(ostream&,const std::vector<T>&) 添加前向声明,它在 operator<<(ostream&, const std::map<K,V>) 和 Clang 编译您的代码.

If you add a forward declaration for operator<<(ostream&,const std::vector<T>&), it becomes unambiguously visible in operator<<(ostream&, const std::map<K,V>) and Clang compiles your code.

只是交换函数也足以让您的特定代码在 Clang 下构建,但如果您尝试这样做,它会再次中断

Just swapping the functions is also enough to get your specific code to build under Clang, but it will break again if you attempt to do

int main()
{
    std::vector<std::map<int, int>> u = {{{1, 2},{3, 4}}, {{4, 5}}};

    std::cout << u << std::endl;

    return 0;
}

因为现在 Clang 不会在 std::vector 的实现中看到 std::map 的正确重载(使用 GCC不过它仍然会很好地构建)

because now Clang will not see the correct overload for std::map<K, V> inside the implementation for std::vector<T> (with GCC it will still build fine though)

这篇关于是否可以定义 operator<<对于模板类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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