【问题标题】:Nested function template instantiation without forward declaration compiles on GCC but not on clang没有前向声明的嵌套函数模板实例化可以在 GCC 上编译,但不能在 clang 上编译
【发布时间】:2021-05-03 13:26:33
【问题描述】:

以下内容不能在 clang 中编译,但在 GCC (godbolt) 中可以:

template <typename K, typename V>
std::ostream& operator<< (std::ostream& o, const std::map<K, V>& map)
{
    const char* sep = "{";
    for (const auto& x : map)
    {
        o << sep << "{" << x.first << ", " << x.second << "}";
        sep = ", ";
    }
    return o << "}";
}

template <typename T>
std::ostream& operator<< (std::ostream& o, const std::vector<T>& vec)
{
    const char* sep = "{";
    for (const auto& x : vec)
    {
        o << sep << x;
        sep = ", ";
    }
    return o << "}";
}

// Usage

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

谁是对的?

顺便说一句,我知道它是 UB,但是将两个模板定义放在 namespace std 中也会使代码在 clang 上编译。

代码借自Is it possible to define operator<< for templated types?

【问题讨论】:

  • 如果你只是交换operator&lt;&lt;重载的顺序,它应该可以编译。
  • @TedLyngmo 是的,但是如果涉及到地图的矢量,那么更改顺序会破坏它^^
  • @Fareanor 当然 - 在这种情况下,必须转发声明。 template &lt;typename T&gt; std::ostream&amp; operator&lt;&lt;(std::ostream&amp; o, const std::vector&lt;T&gt;&amp; vec);
  • @TedLyngmo 同意,我说是因为在链接的问题中,OP 不想转发声明任何内容。
  • @Fareanor 啊,我明白了(我没有阅读借用代码的链接)。

标签: c++ language-lawyer


【解决方案1】:

Clang 是对的。您应该将operator&lt;&lt;std::vector 的声明移到operator&lt;&lt;std::map 的定义之前。

unqualified name lookup

(强调我的)

对于模板定义中使用的依赖名称,查找会推迟到知道模板参数为止,此时 ADL 会检查从模板定义上下文以及模板实例化上下文中可见的函数声明 with external linkage (until C++11) , 虽然非 ADL 查找仅检查从模板定义上下文可见的函数声明 with external linkage (until C++11)(换句话说,在模板定义之后添加新函数声明不会使其可见,除非通过 ADL) .

【讨论】:

  • 我想知道造成这种差异的原因是什么
  • @Danra 关于 Clang 和 Gcc 之间区别的基本原理?
  • ADL 和非 ADL 查找检查的声明之间
  • @Danra Non-ADL 在使用声明之前检查声明,这与非模板函数的工作方式相同。 ADL 检查声明用作参数的类的名称空间。在这种情况下,它们都找不到,因为std::vectoroperator&lt;&lt;std::map 的一个之后声明,那么它是不可见的,并且std::vector 在命名空间std 中声明,但operator&lt;&lt; 在全局命名空间中声明.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-09-22
  • 2014-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多