Re: operator<< template declaration problem

Discussion in 'C++' started by porschberg, Jun 24, 2003.

  1. porschberg

    porschberg Guest

    Of course this works, but then I have to update my template header
    file every time I instantiate a new template.
    This is not very smart. Is there no better way ?

    Chandra Shekhar Kumar <> wrote in message news:<>...
    > keep the implementation in the header file for all the templates
    >
    > porschberg wrote:
    >
    > > Hello,
    > > I try to find a template implementation for a set of classes and thereby
    > > I encounter problems with the operator<<.
    > > The origin class layout looks as follows:
    > >
    > > P_WHReasonUpdate.hh
    > > ===================
    > > //a class to perform a update on table P_WHReason
    > > class P_WHReasonUpdate
    > > {
    > > public:
    > > ...
    > > ...
    > > class row{
    > > ...
    > > }
    > >
    > > typedef shared_ptr<P_WHReasonUpdate::row> ROW;
    > > typedef vector<ROW>::iterator iter;
    > > typedef pair<iter, iter>iterPair;
    > > privat:
    > > otl_connect& db;
    > > otl_nocommit_stream i;
    > > size_t array_size;
    > > vector<ROW> v;
    > > ...
    > > };
    > >
    > > otl_stream& operator<<(otl_stream& s, const P_WHReasonUpdate::row& row);
    > >
    > > P_WHReasonUpdate.cc
    > > ===================
    > >
    > > otl_stream& operator<<(otl_stream& s, const P_WHReasonUpdate::ROW & row)
    > > {
    > > ... impl ...
    > > return s;
    > > }
    > >
    > > void P_WHReasonUpdate::flush()
    > > {
    > > ...
    > > i << (*myIterator); // i is of type otl_stream
    > > ...
    > > }
    > >
    > > All this works fine....
    > > -------------------------------
    > >
    > > Now my template attempt (Update.hh):
    > >
    > > template <class T>
    > > class Update
    > > {
    > > public:
    > >
    > > typedef shared_ptr<typename T::row> ROW;
    > > typedef typename vector<ROW>::iterator iter;
    > > friend otl_stream& operator<< <> (otl_stream &output, const typename T::row& row);
    > > ...
    > > ...
    > > };
    > >
    > > //Use of the template in a test.cc
    > > Update<P_WHReasonUpdate> myUpdate(db);
    > >
    > > In Update.hh I still have my flush() method which does
    > >
    > > i << (*myIterator); // i is of type otl_stream
    > >
    > > The implementation of the overloaded operator<< is
    > > still in P_WHReasonUpdate.cc and therefore without the friend line
    > > I get from the compiler:
    > > Update.hh:109: error: no match for `otl_tmpl_nocommit_stream<otl_stream, ...
    > >
    > > With the friend line I get:
    > > Update.hh:39: error: template-id `operator<< <>' for `otl_stream&
    > > operator<<(otl_stream&, const P_WHReasonUpdate::row&)' does not match any
    > > template declaration
    > >
    > > I think I need a forward declaration of the operator-overloading in my
    > > template class Update.hh and at link time the implementation from
    > > P_WHReasonUpdate.cc will used.
    > >
    > > My question: What is the way to achieve this ?
    > >
    > > Thanks for every help !
    > > Thomas
    porschberg, Jun 24, 2003
    #1
    1. Advertising

  2. porschberg

    tom_usenet Guest

    On 23 Jun 2003 22:25:14 -0700,
    (porschberg) wrote:

    >Of course this works, but then I have to update my template header
    >file every time I instantiate a new template.
    >This is not very smart. Is there no better way ?


    No, implicit instantation automatically creates the required
    instantiations - this is why putting template definitions in the
    header is the norm, since it requires no special maintenance. It does
    however mean that code that uses the template is dependent on its
    implementation.

    But there is another way. Read down.

    >> > Now my template attempt (Update.hh):
    >> >
    >> > template <class T>
    >> > class Update
    >> > {
    >> > public:
    >> >
    >> > typedef shared_ptr<typename T::row> ROW;
    >> > typedef typename vector<ROW>::iterator iter;
    >> > friend otl_stream& operator<< <> (otl_stream &output, const typename T::row& row);


    Make the above a non-template. You aren't going to be able to deduce T
    in a call anyway. Consider this:

    struct Foo
    {
    typedef int row;
    };

    struct Bar
    {
    typedef int row;
    };

    otl_stream << 5; //calls operator<< <Foo> or <Bar>!?

    You can't deduce template arguments from nested types. So change your
    friend declaration to:

    //non-template friend:
    friend otl_stream& operator<<(otl_stream &output, const typename
    T::row& row);



    >> > ...
    >> > ...
    >> > };
    >> >


    In update.cc:

    otl_stream& operator<<(otl_stream &output, const int& row)
    {
    //definition
    }

    otl_stream& operator<<(otl_stream &output, const whatever& row)
    {
    //definition
    }

    etc. Obviously, you could use another template in the .cc file and
    forward the definitions to that to save duplication.


    >> > //Use of the template in a test.cc
    >> > Update<P_WHReasonUpdate> myUpdate(db);
    >> >
    >> > In Update.hh I still have my flush() method which does
    >> >
    >> > i << (*myIterator); // i is of type otl_stream
    >> >
    >> > The implementation of the overloaded operator<< is
    >> > still in P_WHReasonUpdate.cc and therefore without the friend line
    >> > I get from the compiler:
    >> > Update.hh:109: error: no match for `otl_tmpl_nocommit_stream<otl_stream, ...
    >> >
    >> > With the friend line I get:
    >> > Update.hh:39: error: template-id `operator<< <>' for `otl_stream&
    >> > operator<<(otl_stream&, const P_WHReasonUpdate::row&)' does not match any
    >> > template declaration
    >> >
    >> > I think I need a forward declaration of the operator-overloading in my
    >> > template class Update.hh and at link time the implementation from
    >> > P_WHReasonUpdate.cc will used.
    >> >
    >> > My question: What is the way to achieve this ?


    Not with the template as is, since template argument deduction cannot
    work on the template as you have currently written it. However, in the
    normal case you do this:

    In .h:

    template class forward declaration

    template function (needing friendship) forward declaration

    template class definition, including friend (as you wrote it)

    In .cpp

    Explicit instantion of required versions.

    Tom
    tom_usenet, Jun 24, 2003
    #2
    1. Advertising

  3. porschberg

    porschberg Guest

    Thanks a lot for your advice.
    I still get a compiler warning

    Update.hh:63: warning: friend declaration `otl_stream& operator<<(otl_stream&,
    const boost::shared_ptr<typename T::row>&)' declares a non-template function
    Update.hh:63: warning: (if this is not what you intended, make sure the
    function template has already been declared and add <> after the function
    name here) -Wno-non-template-friend disables this warning

    but there is nothing wrong with operator<< because it is not a
    template function. Right?!
    My real implementation is in *.cc.

    (tom_usenet) wrote in message news:<>...
    > On 23 Jun 2003 22:25:14 -0700,
    > (porschberg) wrote:
    >
    > >Of course this works, but then I have to update my template header
    > >file every time I instantiate a new template.
    > >This is not very smart. Is there no better way ?

    >
    > No, implicit instantation automatically creates the required
    > instantiations - this is why putting template definitions in the
    > header is the norm, since it requires no special maintenance. It does
    > however mean that code that uses the template is dependent on its
    > implementation.
    >
    > But there is another way. Read down.
    >
    > >> > Now my template attempt (Update.hh):
    > >> >
    > >> > template <class T>
    > >> > class Update
    > >> > {
    > >> > public:
    > >> >
    > >> > typedef shared_ptr<typename T::row> ROW;
    > >> > typedef typename vector<ROW>::iterator iter;
    > >> > friend otl_stream& operator<< <> (otl_stream &output, const typename T::row& row);

    >
    > Make the above a non-template. You aren't going to be able to deduce T
    > in a call anyway. Consider this:
    >
    > struct Foo
    > {
    > typedef int row;
    > };
    >
    > struct Bar
    > {
    > typedef int row;
    > };
    >
    > otl_stream << 5; //calls operator<< <Foo> or <Bar>!?
    >
    > You can't deduce template arguments from nested types. So change your
    > friend declaration to:
    >
    > //non-template friend:
    > friend otl_stream& operator<<(otl_stream &output, const typename
    > T::row& row);
    >
    >
    >
    > >> > ...
    > >> > ...
    > >> > };
    > >> >

    >
    > In update.cc:
    >
    > otl_stream& operator<<(otl_stream &output, const int& row)
    > {
    > //definition
    > }
    >
    > otl_stream& operator<<(otl_stream &output, const whatever& row)
    > {
    > //definition
    > }
    >
    > etc. Obviously, you could use another template in the .cc file and
    > forward the definitions to that to save duplication.
    >
    >
    > >> > //Use of the template in a test.cc
    > >> > Update<P_WHReasonUpdate> myUpdate(db);
    > >> >
    > >> > In Update.hh I still have my flush() method which does
    > >> >
    > >> > i << (*myIterator); // i is of type otl_stream
    > >> >
    > >> > The implementation of the overloaded operator<< is
    > >> > still in P_WHReasonUpdate.cc and therefore without the friend line
    > >> > I get from the compiler:
    > >> > Update.hh:109: error: no match for `otl_tmpl_nocommit_stream<otl_stream, ...
    > >> >
    > >> > With the friend line I get:
    > >> > Update.hh:39: error: template-id `operator<< <>' for `otl_stream&
    > >> > operator<<(otl_stream&, const P_WHReasonUpdate::row&)' does not match any
    > >> > template declaration
    > >> >
    > >> > I think I need a forward declaration of the operator-overloading in my
    > >> > template class Update.hh and at link time the implementation from
    > >> > P_WHReasonUpdate.cc will used.
    > >> >
    > >> > My question: What is the way to achieve this ?

    >
    > Not with the template as is, since template argument deduction cannot
    > work on the template as you have currently written it. However, in the
    > normal case you do this:
    >
    > In .h:
    >
    > template class forward declaration
    >
    > template function (needing friendship) forward declaration
    >
    > template class definition, including friend (as you wrote it)
    >
    > In .cpp
    >
    > Explicit instantion of required versions.
    >
    > Tom
    porschberg, Jun 24, 2003
    #3
  4. porschberg

    tom_usenet Guest

    On 24 Jun 2003 06:19:31 -0700,
    (porschberg) wrote:

    >Thanks a lot for your advice.
    >I still get a compiler warning
    >
    >Update.hh:63: warning: friend declaration `otl_stream& operator<<(otl_stream&,
    > const boost::shared_ptr<typename T::row>&)' declares a non-template function
    >Update.hh:63: warning: (if this is not what you intended, make sure the
    > function template has already been declared and add <> after the function
    > name here) -Wno-non-template-friend disables this warning
    >
    >but there is nothing wrong with operator<< because it is not a
    >template function. Right?!


    Right. Normally it is a mistake (you intended a template function),
    but in your case it isn't. That looks like a gcc warning. See here:

    http://gcc.gnu.org/faq.html#friend

    Tom
    tom_usenet, Jun 24, 2003
    #4
    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:
    640
    Leor Zolman
    Apr 4, 2004
  2. blueblueblue2005
    Replies:
    6
    Views:
    1,000
    blueblueblue2005
    Jul 19, 2005
  3. Alex Buell
    Replies:
    2
    Views:
    653
    Alex Buell
    Feb 21, 2006
  4. Joseph Turian
    Replies:
    2
    Views:
    851
    Joseph Turian
    Mar 22, 2007
  5. Adam Nielsen
    Replies:
    3
    Views:
    408
Loading...

Share This Page