有样品
// 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);
}
Run Code Online (Sandbox Code Playgroud)
摘自"Exceptional C++:47工程难题,编程问题和解决方案" - 第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);
}
Run Code Online (Sandbox Code Playgroud)
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;
~~~~~~~^~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
看起来像g ++中的bug.我很想知道变通方法是否存在?
如果有人像我一样好奇 - 我会通过书中的进一步阅读发表我所理解的内容.
编译器将从命名空间std开始查找从std :: accumulate调用的operator +.
只有在命名空间中找不到候选者时 - 它才会上升并寻找全局命名空间候选者.
所以clang中的原始样本和修改后的样本是纯粹运气编译的,在std :: accumulate之前没有声明operator +.
一旦在游戏中添加了新的标题 - 编译器就会停止查看全局命名空间并停止将适当的操作符视为候选者.
最佳匹配不是那么好,并导致所有这些奇怪的错误消息.
现在,移动运营商+到名字空间n为发起Koenig查找 - 如果函数参数之一是命名空间中的N - 合适的人选应该在这个命名空间以及除了常规的查找来看待.