Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

adding <iostream> breaks the code in g++-7

Tags:

c++

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?

like image 732
Artemy Vysotsky Avatar asked Sep 11 '17 19:09

Artemy Vysotsky


1 Answers

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.

like image 169
Artemy Vysotsky Avatar answered Oct 30 '22 06:10

Artemy Vysotsky