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

标签 c++

有 sample

// 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);
}

来自“卓越的 C++:47 个工程难题、编程问题和解决方案”——第 34 项。名称查找和接口(interface)原则​​——第 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++ 中的错误。我想知道是否存在解决方法?

最佳答案

如果有人像我一样好奇 - 我将发布我通过进一步阅读本书所理解的内容。

编译器将查找从命名空间 std 开始的 std::accumulate 调用的 operator+。

只有在命名空间中没有找到候选者时 - 它会向上寻找全局命名空间候选者。

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

一旦将新 header 添加到游戏中 - 编译器就会停止查看全局命名空间,并且根本不会将合适的运算符视为候选对象。

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

现在将 operator+ 移动到 namespace N 会启动 Koenig 查找 - 如果其中一个函数参数在 namespace N 中 - 应该在此 namespace 中查找合适的候选者以及常规查找的补充。

关于c++ - 添加 <iostream> 会破坏 g++-7 中的代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46163095/

相关文章:

c++ - *p++ += 2 定义明确吗?

c++ - 这在 C++ 模板中意味着什么?

c++ - 确定是否所有需要的头文件都包含在另一个头文件中

c++ - 处理灰度模板匹配中的亮度

c++ - std::string 到 LPOLESTR

C++ FANN fann_run 始终产生相同的输出

c++ - 如何计算以下函数的时间复杂度?

c++ - 来自 html 的 Qt 中的字符串匹配

c++ - 如何将模板模板与模板实例进行比较?

c++ - 将 vector 堆叠到特征矩阵中