添加<iostream>会破坏g ++ - 7中的代码

时间:2017-09-11 19:27:38

标签: c++

有样本

// Example 2: Will this compile? 
//
// In some library header:
namespace N { class C {}; }
int operator+(int i, N::C) { return i+1; }
// A mainline to exercise it:
#include <numeric>
int main()
{
  N::C a[10];
  std::accumulate(a, a+10, 0);
}

From&#34; Exceptional C ++:47工程难题,编程问题和解决方案&#34; - 项目34.名称查找和接口原则​​ - 第4部分

g ++ 5.4成功编译。 但添加#include <iostream>会破坏代码

// Example 2: Will this compile? 
//
// In some library header:
namespace N { class C {}; }
int operator+(int i, N::C) { return i+1; }
// A mainline to exercise it:
#include <numeric>
#include <iostream>
int main()
{
    N::C a[10];
    std::accumulate(a, a+10, 0);
}

clang-4.0能够编译它。 g ++ 5.4和g ++ 7.2.0显示他跟随错误

In file included from /usr/include/c++/7/numeric:62:0,
                 from src/widget.cpp:7:
/usr/include/c++/7/bits/stl_numeric.h: In instantiation of ‘_Tp std::accumulate(_InputIterator, _InputIterator, _Tp) [with _InputIterator = N::C*; _Tp = int]’:
src/widget.cpp:12:35:   required from here
/usr/include/c++/7/bits/stl_numeric.h:127:18: error: no match for ‘operator+’ (operand types are ‘int’ and ‘N::C’)
  __init = __init + *__first;
           ~~~~~~~^~~~~~~~~~

看起来像g ++中的bug。我有兴趣知道是否存在变通方法吗?

1 个答案:

答案 0 :(得分:6)

如果有人像我这样的好奇心 - 我会在书中进一步阅读我发表的内容。

编译器将从命名空间std。

开始查找从std :: accumulate调用的operator +

只有在命名空间中找不到候选者时 - 它才会上升并寻找全局命名空间候选者。

所以clang中的原始样本和修改后的样本是纯粹运气编译的,在std :: accumulate之前没有声明operator +。

只要在游戏中添加了新标题,编译器就会停止查看全局命名空间并停止将适当的运算符视为候选运算符。

最佳匹配不是很好,导致所有这些奇怪的错误消息。

现在将operator +移动到命名空间N启动Koenig查找 - 如果其中一个函数参数位于命名空间N中 - 应该在此命名空间中查找合适的候选项以及添加常规查找。