friend operator<< in template classes

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Amadeus W. M.

    #1

    friend operator<< in template classes

    What is the difference between

    friend ostream & operator<<(ostr eam & OUT, const Foo & f){
    // output f
    return OUT;
    }

    and

    template <class X>
    friend ostream & operator<<(ostr eam & OUT, const Foo<X> & f){
    // output f
    return OUT;
    }

    either one defined INSIDE a

    template <class T>
    class Foo
    {
    //
    };

    They both work, but is there a difference? The latter is a
    template function inside a template class, right? I understand that part.
    But why doesn't the former need template<class X> and Foo<X>& ?

    I use these on a daily basis, and suddenly I felt the urge for
    clarification. Thanks!

  • Bo Persson

    #2
    Re: friend operator&lt;&lt ; in template classes


    "Amadeus W. M." <amadeus84@cabl espeed.com> skrev i meddelandet
    news:pan.2006.0 1.22.02.56.24.7 91667@cablespee d.com...[color=blue]
    > What is the difference between
    >
    > friend ostream & operator<<(ostr eam & OUT, const Foo & f){
    > // output f
    > return OUT;
    > }
    >
    > and
    >
    > template <class X>
    > friend ostream & operator<<(ostr eam & OUT, const Foo<X> & f){
    > // output f
    > return OUT;
    > }
    >
    > either one defined INSIDE a
    >
    > template <class T>
    > class Foo
    > {
    > //
    > };
    >
    > They both work, but is there a difference? The latter is a
    > template function inside a template class, right? I understand that
    > part.
    > But why doesn't the former need template<class X> and Foo<X>& ?[/color]

    The difference is, like you say, that the first version defines a
    single friend operator. The second one defines a whole group of
    friends, one for each possible X. In this particual case, that doesn't
    seem neccessary.




    Bo Persson


    Comment

    • John Carson

      #3
      Re: friend operator&lt;&lt ; in template classes

      "Bo Persson" <bop@gmb.dk> wrote in message
      news:43h592F1nj n9jU1@individua l.net[color=blue]
      > "Amadeus W. M." <amadeus84@cabl espeed.com> skrev i meddelandet
      > news:pan.2006.0 1.22.02.56.24.7 91667@cablespee d.com...[color=green]
      >> What is the difference between
      >>
      >> friend ostream & operator<<(ostr eam & OUT, const Foo & f){
      >> // output f
      >> return OUT;
      >> }
      >>
      >> and
      >>
      >> template <class X>
      >> friend ostream & operator<<(ostr eam & OUT, const Foo<X> & f){
      >> // output f
      >> return OUT;
      >> }
      >>
      >> either one defined INSIDE a
      >>
      >> template <class T>
      >> class Foo
      >> {
      >> //
      >> };
      >>
      >> They both work, but is there a difference? The latter is a
      >> template function inside a template class, right? I understand that
      >> part.
      >> But why doesn't the former need template<class X> and Foo<X>& ?[/color]
      >
      > The difference is, like you say, that the first version defines a
      > single friend operator. The second one defines a whole group of
      > friends, one for each possible X. In this particual case, that doesn't
      > seem neccessary.[/color]

      That is not the difference. When defined inside the class definition, the
      first version is also a template operator. Consider:

      #include <iostream>
      using namespace std;


      template <class T>
      class Foo
      {
      T x;
      public:
      Foo(const T& arg) : x(arg)
      {}
      friend ostream & operator<< (ostream & out, const Foo & f)
      {
      out << f.x;
      return out;
      }
      };

      int main()
      {
      Foo<int> f(5);
      cout << f << endl;

      Foo<string> g("Text");
      cout << g << endl;

      return 0;
      }

      Apparently it makes all the difference whether the friend operator is
      defined inside or outside the class. In the former case, the template form
      is implicit, just as it is in, say, the definition of the Foo constructor or
      any other member function.


      --
      John Carson


      Comment

      • Bo Persson

        #4
        Re: friend operator&lt;&lt ; in template classes


        "John Carson" <jcarson_n_o_sp _am_@netspace.n et.au> skrev i meddelandet
        news:43d3637f$0 $1042$61c65585@ un-2park-reader-01.sydney.pipen etworks.com.au. ..[color=blue]
        > "Bo Persson" <bop@gmb.dk> wrote in message
        > news:43h592F1nj n9jU1@individua l.net[color=green]
        >> "Amadeus W. M." <amadeus84@cabl espeed.com> skrev i meddelandet
        >> news:pan.2006.0 1.22.02.56.24.7 91667@cablespee d.com...[color=darkred]
        >>> What is the difference between
        >>>
        >>> friend ostream & operator<<(ostr eam & OUT, const Foo & f){
        >>> // output f
        >>> return OUT;
        >>> }
        >>>
        >>> and
        >>>
        >>> template <class X>
        >>> friend ostream & operator<<(ostr eam & OUT, const Foo<X> & f){
        >>> // output f
        >>> return OUT;
        >>> }
        >>>
        >>> either one defined INSIDE a
        >>>
        >>> template <class T>
        >>> class Foo
        >>> {
        >>> //
        >>> };
        >>>
        >>> They both work, but is there a difference? The latter is a
        >>> template function inside a template class, right? I understand
        >>> that
        >>> part.
        >>> But why doesn't the former need template<class X> and Foo<X>& ?[/color]
        >>
        >> The difference is, like you say, that the first version defines a
        >> single friend operator. The second one defines a whole group of
        >> friends, one for each possible X. In this particual case, that
        >> doesn't
        >> seem neccessary.[/color]
        >
        > That is not the difference. When defined inside the class
        > definition, the first version is also a template operator.[/color]

        Yes, it's templated on T, as Foo means Foo<T> in this context. But
        there is only one friend operator<< for each specific instantiation of
        Foo.

        The template<class X> version makes each operator<< a friend of all
        Foo's. This means that that

        template<>
        ostream& operator(ostrea m&, const Foo<A>&)

        will have access to the internals of Foo<B>, Foo<C>, etc. The
        non-template version will not.


        Bo Persson


        Comment

        • Amadeus W. M.

          #5
          Re: friend operator&lt;&lt ; in template classes

          On Sun, 22 Jan 2006 14:51:49 +0100, Bo Persson wrote:
          [color=blue]
          >
          > "John Carson" <jcarson_n_o_sp _am_@netspace.n et.au> skrev i meddelandet
          > news:43d3637f$0 $1042$61c65585@ un-2park-reader-01.sydney.pipen etworks.com.au. ..[color=green]
          >> "Bo Persson" <bop@gmb.dk> wrote in message
          >> news:43h592F1nj n9jU1@individua l.net[color=darkred]
          >>> "Amadeus W. M." <amadeus84@cabl espeed.com> skrev i meddelandet
          >>> news:pan.2006.0 1.22.02.56.24.7 91667@cablespee d.com...
          >>>> What is the difference between
          >>>>
          >>>> friend ostream & operator<<(ostr eam & OUT, const Foo & f){
          >>>> // output f
          >>>> return OUT;
          >>>> }
          >>>>
          >>>> and
          >>>>
          >>>> template <class X>
          >>>> friend ostream & operator<<(ostr eam & OUT, const Foo<X> & f){
          >>>> // output f
          >>>> return OUT;
          >>>> }
          >>>>
          >>>> either one defined INSIDE a
          >>>>
          >>>> template <class T>
          >>>> class Foo
          >>>> {
          >>>> //
          >>>> };
          >>>>
          >>>> They both work, but is there a difference? The latter is a
          >>>> template function inside a template class, right? I understand
          >>>> that
          >>>> part.
          >>>> But why doesn't the former need template<class X> and Foo<X>& ?
          >>>
          >>> The difference is, like you say, that the first version defines a
          >>> single friend operator. The second one defines a whole group of
          >>> friends, one for each possible X. In this particual case, that
          >>> doesn't
          >>> seem neccessary.[/color]
          >>
          >> That is not the difference. When defined inside the class
          >> definition, the first version is also a template operator.[/color]
          >
          > Yes, it's templated on T, as Foo means Foo<T> in this context. But
          > there is only one friend operator<< for each specific instantiation of
          > Foo.
          >
          > The template<class X> version makes each operator<< a friend of all
          > Foo's. This means that that
          >
          > template<>
          > ostream& operator(ostrea m&, const Foo<A>&)
          >
          > will have access to the internals of Foo<B>, Foo<C>, etc. The
          > non-template version will not.
          >
          >
          > Bo Persson[/color]

          So, in the "non-templated" version, if I have

          Foo<A> a; // A's version of operator<< is instantiated here, with Foo<A>
          Foo<B> b; // b's version of operator<< is instantiated.

          cout << a; // operator<<(ostr eam &, const Foo<A> &) is called.
          cout << b; // operator<<(ostr eam &, const Foo<B> &) is called.

          The two versions of operator<<() are different, but from the user's
          standpoint, it doesn't matter that the Foo<B> version of operator<<
          does not have access to Foo<A>'s internals. The instantiation of
          operator<<() for each type A and B occurs whether or not we call
          them.


          On the other hand, in the templated case, operator<<() is not
          actually instantiated UNLESS we call cout << a; cout << b;

          Again, it is irrelevant to the user whether or not A's version of
          operator<< has access to B's internals.

          Is this the point?

          Comment

          Working...