3

I want to overload the output stream operator << outside the template class definition.

Implementing it inside the template class is ok:

template
<typename T,int _MaxSize=10,template <class C> class Policy=NoCheck,typename Container=std::vector<T>>
class MyContainer : public Policy<T>
{
public:
  MyContainer():p(_MaxSize){};
  std::ostream& operator<<(MyContainer<T,_MaxSize,Policy,Container>& obj){ };
private:
  Container p;
};

But when I tried to do it outside the template class:

template
<typename T,int _MaxSize=10,template <class C> class Policy=NoCheck,typename Container=std::vector<T>>
class MyContainer : public Policy<T>
{
public:
  MyContainer():p(_MaxSize){};
  friend std::ostream& operator<<(std::ostream& out,MyContainer<T,_MaxSize,Policy,Container> obj);
private:
  Container p;
};

template
<typename T,int _MaxSize,template <class C> class Policy,typename Container>
std::ostream& operator<<(std::ostream& out,MyContainer<T,_MaxSize,Policy,Container> obj)
{
};

Compiler complains:

warning: friend declaration ‘std::ostream& operator<<(std::ostream&, MyContainer<T, _MaxSize, Policy, Container>)’ declares a non-template function [-Wnon-template-friend]
tempstruct.cc:39:97: note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)

Can anybody give a simple example on how can the output stream operator << defined outside a template class?

In the related posts that I found here everyone do it inside the template class.

3
  • 2
    Just stop and think for a moment: "does it really need to be a friend?"
    – BoBTFish
    Commented May 29, 2013 at 12:42
  • @BoBTFish I am not sure about the answer. I used to declare it as a friend in my non-template classes. Commented May 29, 2013 at 12:47
  • Does it use any private member data or functions? Does it have to?
    – BoBTFish
    Commented May 29, 2013 at 12:48

1 Answer 1

5

Can anybody give a simple example on how can the output stream operator << defined outside a template class?

No, because it's not simple. I can give a complicated example:

// Declare the class template, because we need it to declare the operator
template <typename,int,template <class C> class,typename> class MyContainer;

// Declare the operator, because (as the error says) templates must be declared
// in the namespace before you can declare them friends. At this point, we can't
// define the operator, since the class template is incomplete.
template 
<typename T,int _MaxSize,template <class C> class Policy,typename Container>
std::ostream& operator<<(std::ostream&,MyContainer<T,_MaxSize,Policy,Container>);

// Define the class template
template
<typename T,int _MaxSize=10,template <class C> class Policy=NoCheck,typename Container=std::vector<T>>
class MyContainer : public Policy<T>
{
public:
  MyContainer():p(_MaxSize){};

  // Include <> to indicate that this is the template
  friend std::ostream& operator<< <>(std::ostream& out,MyContainer<T,_MaxSize,Policy,Container> obj);
private:
  Container p;
};

// Finally define the operator
template
<typename T,int _MaxSize,template <class C> class Policy,typename Container>
std::ostream& operator<<(std::ostream& out,MyContainer<T,_MaxSize,Policy,Container> obj)
{
  // print some stuff
};

In the related posts that I found here everyone do it inside the template class.

I'd do that; it would be much simpler. Or, better still, I'd implement output in terms of the public interface, assuming it gives sufficient access to the container's contents. Then you wouldn't need the friend declaration, so wouldn't need the forward declarations either.

1
  • Thank you very much Mike. That's what I wanted. I get it. Commented May 29, 2013 at 12:52

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