smallB
smallB

Reputation: 17120

How to declare operator<< for internal class

//cannot declare operator<<(...) here:
//forward declarations:
class External;

template<class T, class Y>
class External::Internal;

template<class T, class Y>
std::ostream& operator<<(std::ostream& out, const External::Internal<T,Y>&);

class External
{
    template<class T, class Y>
    class Internal
    {};

    Internal data_;

    void print() {
        /*out is a std::ostream*/
        out << data_;
    }
};

template<class T, class Y>
std::ostream& operator<<(std::ostream& out, const External::Internal<T,Y>&)
{ }

I do want to implement operator<< for Internal but there is a problem when I try to use this operator call from External: It doesn't see this operator when this operator is declared under the definition of this class, and there seems to be no way of declaring this operator above this class definition.

Upvotes: 0

Views: 2275

Answers (6)

ildjarn
ildjarn

Reputation: 62975

If you're asking how to define Internal<>::operator<< as a friend, then:

class External
{
  template<class T, class Y>
  class Internal
  {
    friend std::ostream& operator <<(std::ostream& out, const Internal&)
    {
      // impl
      return out;
    }
  };

  Internal<Foo, Bar> data_;

public:
  void print() const
  {
    /*out is a std::ostream*/
    out << data_;
  }
};

Upvotes: 1

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385164

there is a problem when I try to use this operator call from External

Don't write procedural code inside your class definition. Only declarations.

Write, in order:

  • Class definition [in header]
  • operator<< [in header]
  • Code that uses these things [in source file]

Upvotes: 0

Armen Tsirunyan
Armen Tsirunyan

Reputation: 133004

template<class T, class Y>
std::ostream& operator<<(std::ostream& out,const External::Internal<T, Y>&)
                                                 ^^^^^^^^^^        ^^^^^^
{

}

And make sure to declare this function a friend, because Internal is private in External

Update: here's how you declare a friend. In your class definition write:

template<class T, class Y>
friend  std::ostream& operator <<(std::ostream& out, const External::Internal<T,Y>&)

Since a friend-declaration is a declaration, this will solve your forward-declaration issue.

Update: To solve the circular dependency:

First forward-declare internal

template<class T, class Y>
class Internal;

then declare the friend.

Then the rest of your class, it should work.

Upvotes: 1

Fiktik
Fiktik

Reputation: 1941

The point is in using forward declarations:

// you promise there will be implementation of this stuff later on:
template<typename T, typename Y>
class External::Internal<T, Y>;

template<typename T, typename Y>
std::ostream& operator<<(std::ostream& out, const External::Internal<T, Y>&);

// now declare your class and operator<< function as normal
class External
{
    template<class T, class Y>
    class Internal
    {
    };

    Internal<Foo, Bar> data_;

    void print()
    {
        // here you can use operator<< with Internal
        out << data_;
    }
};

template<class T, class Y>
std::ostream& operator<<(std::ostream& out,const External::Internal<T, Y>&)
{
}

Upvotes: 1

Cheers and hth. - Alf
Cheers and hth. - Alf

Reputation: 145279

Armen's answer would work for the << operator itself.

However, your member declaration

Internal data_;

is also incorrect, in the same way. I.e., lacking template arguments for Internal. So in addition to fixing your operator implementation, fix also your member declaration.

Finally, remember that in C++ you can't use something unless it has already been declared. Your usage of << in the inline implementation of print violates that. So you'd better rearrange things (or just declare them) so that anything that's used, is already declared.

Cheers & hth.,

Upvotes: 1

PetrH
PetrH

Reputation: 1

template<class T, class Y>
std::ostream& operator<<(std::ostream& out, const External::Internal<T, Y>&)
{
}

The External:: behaves as a namespace and is required because operator<< definition is outside of class External.

Upvotes: 0

Related Questions