8

system.h:

#include <iostream>

namespace ss
{
  class system
  {
  private:
    // ...
  public:
    // ...
    friend std::ostream& operator<< (std::ostream& out, const system& sys);

   };
}

system.cpp:

#include "system.h"

std::ostream& ss::operator<< (std::ostream& out, const ss::system& sys)
  {
    // print a representation of the ss::system
    // ...
    return out;
  }

Compiling the above code with g++ 8.30 yields the following output:

[db@dbPC test]$ LANG=en g++ -Wall -Wextra system.cpp
system.cpp:2:15: warning: 'std::ostream& ss::operator<<(std::ostream&, const ss::system&)' has not been declared within 'ss'
 std::ostream& ss::operator<< (std::ostream& out, const ss::system& sys)
               ^~
In file included from system.cpp:1:
system.h:11:26: note: only here as a 'friend'
     friend std::ostream& operator<< (std::ostream& out, const system& sys);
                          ^~~~~~~~
system.cpp: In function 'std::ostream& ss::operator<<(std::ostream&, const ss::system&)':
system.cpp:2:68: warning: unused parameter 'sys' [-Wunused-parameter]
 std::ostream& ss::operator<< (std::ostream& out, const ss::system& sys)
                                                  ~~~~~~~~~~~~~~~~~~^~~

The compiler tells me, that the operator<< function was not declared within the namespace ss. However it is declared within that namespace.

I also tried to compile this with clang++. clang complains only about the unused parameter, but not about the 'not within namespace' issue I do not understand.

What is the cause of the g++ warning? Is this a false warning?

Versions:

g++ (GCC) 8.3.0
clang version: 8.00 (tags/RELEASE_800/final)
M.M
  • 138,810
  • 21
  • 208
  • 365
Danish
  • 407
  • 3
  • 10
  • What if friend is removed? – Michael Chourdakis May 19 '19 at 09:21
  • 6
    The friend declaration does not make the name findable by unqualified lookup in the namespace (technically it is in the namespace, but has not been declared there) – M.M May 19 '19 at 09:22
  • 2
    @M.M but isn't `ss::operator<<(...)` qualified? Agree that un-qualified won't find it (except for ADL), but here we have a qualified definition, so there should be no warning. – vsoftco May 19 '19 at 09:29
  • 1
    I linked now to other questions covering the topic. IMHO the gcc warning is egregious and should be off by default, there is nothing wrong with the code *per se* and in fact I think your code is good practice. But you can suppress the warning with an extra declaration as shown in arsdever's answer – M.M May 19 '19 at 09:50
  • Thanks for the help, I got rid of the warning :D! – Danish May 19 '19 at 11:18

1 Answers1

6

You simply missed declaring the operator << in namespace.

Try the following:

namespace ss
{
  std::ostream& operator << (std::ostream& out, const system& sys);
  class system
  {
  private:
    // ...
  public:
    // ...
    friend std::ostream& operator<< (std::ostream& out, const system& sys);

   };
}

// in cpp

namespace ss
{
  std::ostream& operator << (std::ostream& out, const system& sys)
  {
    // the body
  }
}
Rakete1111
  • 47,013
  • 16
  • 123
  • 162
arsdever
  • 1,111
  • 1
  • 11
  • 32
  • I wonder then what does it mean to define the function out of the namespace? I mean is it simply wrong or was it just an extra warning? – AKL May 19 '19 at 09:30
  • 1
    There is a kind of people that do function definitions only in `.cpp` files. I'm a person of that kind as well. – arsdever May 19 '19 at 09:31
  • where did I remove `ss::`? Did you mean declaration or definition? Notice, that I have written both inside `namespace ss` and there's no longer needed to write `ss::` in front of the function – arsdever May 19 '19 at 09:37
  • 1
    @arsdever, I'm just dumb. I mistook `ss` as the class name and you enclosed the definition in the namespace instead of qualifying the namespace like the OP, so no difference. – chris May 19 '19 at 09:38
  • That is a drastic change in the code semantic. Now any argument implicitly convertible to `system` may cause a call to this function in expressions of the form `a< – Oliv May 19 '19 at 19:07