Re: friend of template class

From: Jarek (jaroosh_at_poczta.wp.pl)
Date: 07/12/04

  • Next message: ToGu: "[OT] Re: inline assert [C++]"
    Date: Mon, 12 Jul 2004 02:43:07 +0200
    
    

    Uzytkownik "Gwar" <xeno@xor.qua> napisal w wiadomosci
    news:20040711150048.Q38088@synergy.transbay.net...
    >
    >
    >
    > I got this to compile & to do what it's suppose to do but I need to
    > know why I must declare the friend function inside the class A thus:
    >
    > template <class T> class A;
    > template <class T> ostream & operator<<(ostream &os, const A<T> &a);
    > template <class T>
    > class A
    > {
    > ...
    > // the question is about the <> after the function name
    > friend ostream & operator << <T> (operator & os, const A<T> &a);
    > };
    >
    > // It wasn't necessary to do this when defining it
    > template <class T> ostream & ostream << (ostream &os, const A<T> &a)
    > {
    > os << a.data_ << endl;
    > return os;
    > }

    This is a complex issue.
    In brief - putting <T> or just <> just before the brackets in :

        friend ostream & operator << <T> (operator & os, const A<T> &a);

    tells the compiler that this operator is a template (if <>/<T> were ommited,
    compiler would be seeking
    non-template definition of operator << (operator & os, const A<T> &a); in
    the global scope where the
    class A is defined, and obviously, it would fail since there is no such
    (non-template) definition).

    You also should (C++ standard requirement I think, though my devc++ compiler
    doesn't actually enforce that) declare the template friend function, this is
    why there are actually two declarations of operator << <T> (operator & os,
    const A<T> &a)
        a) one outside the scope of the class definition since the operator is
    not it's member (and because class A is the operator's argument, the class
    has to be declared also)
        b) second - inside the class definition, just to say that it is it's
    friend

    What actually happens here, is that when you instantiate the template class,
    providing a T - for example with float, (with it's first use)
    a new operator

            friend ostream & operator << <float> (operator & os, const A<T> &a);

    is created and though there might be different instantiations of class A,
    A<int>, A<long>, A<someClass> in the program (and thus,
    as many operator<< instatiations), ONLY this <float> operator is a friend of
    <float> class.
    Since this operator is a TEMPLATE, and it is not a member of class A, we
    can't give compiler a hint where to look for it's definition for the
    particular
    class instantiation, in form of a class quialifier as in case of member
    functions, so we must put <> or <T> to indicate that this operator is bound
    to
    a particular class template.

    This is only necessary when you define the operator OUTSIDE the class
    definition, since if you provide the friend operator's body with the
    declaration,
    compiler doesn't need to look for the operator's definition during the
    linking.
    The code could be then rewritten as follows :

    template <class T>
    class A
    {
     ...
        friend ostream & operator <<(operator & os, const A<T> &a)
        {
          os << a.data_ << endl;
          return os;
        }
    };

    Here, operator << is NOT a template anymore
    By instantiating A to A<int>, A<float> etc. we just get overloaded operators
    like
            operator<<(operator & os, const A<int> &a)
            operator<<(operator & os, const A<float> &a)

    Anyways, putting <>/<T> before the brackets in the operator declaration is a
    C++ standard requirement,
    it helps the compiler link the operator's declaration (which by the time of
    class instantiation might take the form , eg : operator<<(const A<int>&))
    with it's definition (that is yet still a template - if the <>/<T> were
    omited, compiler would assume that operator<<(const A<int>&)) is a
    declaration
    of an ordinary (nontemplate) function, and seek for the EXACT
    operator<<(const A<int>&)) match, but there is no such, since we only have
    template definition for operator<<(const A<T>&)) that is somewhere outside
    the class' definition.
    This is not necessary with the friend operator defined in the class
    definition, since by the time of substituting T for some type/class,
    compiler gets both :
    exact instantiated definition AND it's body.

    ---------
    Cheers
    J.W.


  • Next message: ToGu: "[OT] Re: inline assert [C++]"

    Relevant Pages

    • Re: friend class in template
      ... This template takes 3 type parameters, the first of which is named ... The friend declaration attempts to declare the class ... the friend declaration doesn't do what the author apparently ... thought it would do (at least not on a conforming compiler). ...
      (microsoft.public.vc.language)
    • Re: Template friendship to nested template class
      ... template ... friend struct INNER; ... Both VC and gcc are happy with this code, but the intel compiler is ...
      (microsoft.public.vc.language)
    • Re: Templated friends
      ... > way for a compiler to figure out the template argument from the ... >> to do with friend. ... > of that template are friends), you need to begin your declaration ...
      (comp.lang.cpp)
    • Re: name binding from one template to another
      ... compiler binds another referred template from one template in the ... The compiler can look up primary template itself in the first phase - ... I am wrong that compiler will do nothing to bind the referred ... compiler won't instantiate vector until it has to instantiate func. ...
      (microsoft.public.vc.language)
    • Re: Template Functions
      ... Templates need to be fully visible to the compiler when it generates ... When you don't have an explicit instantiation, ... it is unable to instantiate ... the template, i.e. create the code for that function. ...
      (microsoft.public.vc.language)