4

Consider bar.h:

#include <iostream>

namespace foo {

class Bar {
 public:
  friend std::ostream& operator <<(std::ostream& output, const Bar&);
 private:
  int xx_;
};

}

Consider bar.cc:

#include "bar.h"

std::ostream& operator<<(std::ostream& output, const foo::Bar &in) {

  output << in.xx_ << std::endl;

  return output;
}

Why can't the implementation for operator << access the private member from the Bar class? That is:

$ icpc -c bar.cc
bar.cc(5): error #308: member "foo::Bar::xx_" (declared at line 9 of "bar.h") is inaccessible
    output << in.xx_ << std::endl;
                 ^

compilation aborted for bar.cc (code 2)

I solved the problem by embedding the implementation for operator << inside the foo namespace, i.e.:

namespace foo {
std::ostream& operator<<(std::ostream& output, const foo::Bar &in) {

  output << in.xx_ << std::endl;

  return output;
}
}

Yet... is this the correct way of solving this problem? Isn't this approach giving away details of the implementation?

1
  • 1
    You can also write std::ostream& foo::operator<<(... in the definition, instead of the namespace block. That has the advantage of giving a compilation error if it doesn't match a pre-declared function
    – M.M
    Commented Feb 25, 2015 at 4:39

2 Answers 2

8

Question:

is this the correct way of solving this problem?

Answer:

Yes, it is the correct way of solving the problem.

Question:

Isn't this approach giving away details of the implementation?

Answer:

Not at all.

The line

friend std::ostream& operator <<(std::ostream& output, const Bar&);

declares the function as an external function in the namespace in which the class is defined. If the class is not defined in a namespace, the function is declared as an external function in the global namespace. Since the function is declared as a external function in the foo namespace, it MUST be defined in that namespace.

If you want that function to be a global function, outside the foo namesapce, you have to use:

namespace foo
{
    class Bar;
}

std::ostream& operator <<(std::ostream& output, const foo::Bar&);

namespace foo {

   class Bar {
      public:
         friend std::ostream& operator <<(std::ostream& output, const Bar&);
      private:
         int xx_;
   };
}
3

Because your class Bar is part of the foo namespace you need to define the function within the same namespace.

If you are worried about hiding the implementation details you can still define the function in bar.cc

bar.cc

#include "foo.h"

namespace foo
{

std::ostream& operator<<(std::ostream& output, const Bar &in)
{
        output << "Bar x=" << in.x << std::endl;

        return output;
}

}

Not the answer you're looking for? Browse other questions tagged or ask your own question.