有 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/