Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overloading ostream operator (<<) for class defined within a namespace

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?

like image 750
Eduardo Avatar asked Dec 19 '22 06:12

Eduardo


2 Answers

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_;
   };
}
like image 124
R Sahu Avatar answered Jan 18 '23 23:01

R Sahu


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;
}

}
like image 33
rgoble Avatar answered Jan 18 '23 23:01

rgoble