friend operator<< in template classes

Discussion in 'C++' started by Amadeus W. M., Jan 22, 2006.

  1. What is the difference between

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

    and

    template <class X>
    friend ostream & operator<<(ostream & 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!
     
    Amadeus W. M., Jan 22, 2006
    #1
    1. Advertising

  2. Amadeus W. M.

    Bo Persson Guest

    "Amadeus W. M." <> skrev i meddelandet
    news:p...
    > What is the difference between
    >
    > friend ostream & operator<<(ostream & OUT, const Foo & f){
    > // output f
    > return OUT;
    > }
    >
    > and
    >
    > template <class X>
    > friend ostream & operator<<(ostream & 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.




    Bo Persson
     
    Bo Persson, Jan 22, 2006
    #2
    1. Advertising

  3. Amadeus W. M.

    John Carson Guest

    "Bo Persson" <> wrote in message
    news:
    > "Amadeus W. M." <> skrev i meddelandet
    > news:p...
    >> What is the difference between
    >>
    >> friend ostream & operator<<(ostream & OUT, const Foo & f){
    >> // output f
    >> return OUT;
    >> }
    >>
    >> and
    >>
    >> template <class X>
    >> friend ostream & operator<<(ostream & 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.


    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
     
    John Carson, Jan 22, 2006
    #3
  4. Amadeus W. M.

    Bo Persson Guest

    "John Carson" <> skrev i meddelandet
    news:43d3637f$0$1042$...
    > "Bo Persson" <> wrote in message
    > news:
    >> "Amadeus W. M." <> skrev i meddelandet
    >> news:p...
    >>> What is the difference between
    >>>
    >>> friend ostream & operator<<(ostream & OUT, const Foo & f){
    >>> // output f
    >>> return OUT;
    >>> }
    >>>
    >>> and
    >>>
    >>> template <class X>
    >>> friend ostream & operator<<(ostream & 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.

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


    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(ostream&, const Foo<A>&)

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


    Bo Persson
     
    Bo Persson, Jan 22, 2006
    #4
  5. On Sun, 22 Jan 2006 14:51:49 +0100, Bo Persson wrote:

    >
    > "John Carson" <> skrev i meddelandet
    > news:43d3637f$0$1042$...
    >> "Bo Persson" <> wrote in message
    >> news:
    >>> "Amadeus W. M." <> skrev i meddelandet
    >>> news:p...
    >>>> What is the difference between
    >>>>
    >>>> friend ostream & operator<<(ostream & OUT, const Foo & f){
    >>>> // output f
    >>>> return OUT;
    >>>> }
    >>>>
    >>>> and
    >>>>
    >>>> template <class X>
    >>>> friend ostream & operator<<(ostream & 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.

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

    >
    > 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(ostream&, const Foo<A>&)
    >
    > will have access to the internals of Foo<B>, Foo<C>, etc. The
    > non-template version will not.
    >
    >
    > Bo Persson


    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<<(ostream &, const Foo<A> &) is called.
    cout << b; // operator<<(ostream &, 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?
     
    Amadeus W. M., Jan 22, 2006
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Yu Lianqing
    Replies:
    1
    Views:
    643
    Leor Zolman
    Apr 4, 2004
  2. CoolPint
    Replies:
    3
    Views:
    496
    Victor Bazarov
    Feb 13, 2005
  3. Replies:
    4
    Views:
    531
    Greg Comeau
    Sep 30, 2006
  4. Joe Hesse
    Replies:
    3
    Views:
    481
    want.to.be.professer
    Dec 7, 2007
  5. A L
    Replies:
    1
    Views:
    511
    Alf P. Steinbach /Usenet
    Aug 25, 2010
Loading...

Share This Page