There is 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);
}
From "Exceptional C++: 47 Engineering Puzzles, Programming Problems, and Solutions" -- Item 34. Name Lookup and the Interface Principle—Part 4
g++ 5.4 compiles it successfully.
But adding #include <iostream>
breaks the code
// 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 is able to compile it. g++ 5.4 and g++7.2.0 show he following error
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;
~~~~~~~^~~~~~~~~~
Looks like bug in g++. I'm interested to know if workaround exists?
IF somebody as curios as me - I'm posting what I have understood from further reading in the book.
Compiler will look for operator+ called from std::accumulate starting with namespace std.
Only if no candidates found in the namespace - it will go up and look for global namespace candidates.
So original sample and modified sample in clang were compiled by pure luck that no operator+ was declared before std::accumulate.
As soon as new header was added to the game - compiler stopped to look into the global namespace and stopped seeing proper operator as candidate at all.
Best match was not so good and cause all this strange error messages.
Now moving operator+ into namespace N was initiating Koenig lookup - if one of the function arguments is in the namespace N - suitable candidates should be looked in this namespace as well as addition to regular lookup.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With