Help on correct usage of forward declaration of templates

Discussion in 'C++' started by Hunk, Jan 8, 2007.

  1. Hunk

    Hunk Guest

    Hi

    I have a question on usage of forward declarations of templates. While
    searching through this group , people suggested using forward
    declarations and typedefs for templates as

    // in myfile.h
    template<typename T,typename R>
    class some_class;

    typedef some_class<int,float> my_class;

    then use my_class as an instance in the program. The advantage in this
    is obviously i dont have to include the header file declaring
    some_class. This would help in recompilation dependencies.

    Now i tried out the same as shown below. Note: i have mentioned the
    errors in comments


    //c_reg.h
    template<typename T,typename R>
    class c_reg
    {
    virtual R get_data(T p_data);
    virtual void set_data(T , R);
    }

    template<typename T,typename R> R c_reg::get_data(T p_data)
    {
    ... //do something
    }

    template <typename T,typename R> void c_reg::set_data(T p_key, R
    p_data)
    {
    ... //do something
    }
    //end of c_reg.h

    ------------------------------------------------------------------------------------
    //c_reg_init.h

    // below forward declaration gives error
    // error is "declaration of struct c_my_reg"
    template<T,R>
    class c_reg;
    typedef c_reg<int,std::string> c_my_reg;

    // also gives error here saying
    // invlaid use of undefined type c_my_reg
    template<typename T>
    class c_reg_init : public c_my_reg
    {
    void set_data (int, std::string)
    }

    template<typename T> void c_reg_init<T>::set_data(int, std::string)
    {
    ...//do something
    }
    //end of c_reg_init.h

    Now as seen above, i'm tyring to avoid inclusion of c_reg.h in
    c_reg_init header file. But using the forward declaration syntax gives
    errror mentioned above. It assumes the forward declared template class
    c_reg to be a struct i dont know why.

    What i want to basically do is hide the template header file so that i
    can give the user a interface. In this interface i should be able to
    just forward declare the template class
    Is there a way around?
    Hunk, Jan 8, 2007
    #1
    1. Advertising

  2. Hunk

    Ondra Holub Guest

    Hunk napsal:
    > Hi
    >
    > I have a question on usage of forward declarations of templates. While
    > searching through this group , people suggested using forward
    > declarations and typedefs for templates as
    >
    > // in myfile.h
    > template<typename T,typename R>
    > class some_class;
    >
    > typedef some_class<int,float> my_class;
    >
    > then use my_class as an instance in the program. The advantage in this
    > is obviously i dont have to include the header file declaring
    > some_class. This would help in recompilation dependencies.


    Well, you do not need it, if you want to declare pointer or reference
    to my_class. But if you need to access any method (or attribute) of
    this class, you need the definition of this class as well as in case
    you need to declare instance of this class.

    It is the same as in following example without templates:
    class X;

    X& rx; // OK
    X* px; // OK
    X x; // Error

    void X::method() // Error - nothing is known about methods of class X
    {
    }

    > Now i tried out the same as shown below. Note: i have mentioned the
    > errors in comments
    >
    >
    > //c_reg.h
    > template<typename T,typename R>
    > class c_reg
    > {
    > virtual R get_data(T p_data);
    > virtual void set_data(T , R);
    > }
    >
    > template<typename T,typename R> R c_reg::get_data(T p_data)
    > {
    > ... //do something
    > }
    >
    > template <typename T,typename R> void c_reg::set_data(T p_key, R
    > p_data)
    > {
    > ... //do something
    > }
    > //end of c_reg.h
    >
    > ------------------------------------------------------------------------------------
    > //c_reg_init.h
    >
    > // below forward declaration gives error
    > // error is "declaration of struct c_my_reg"
    > template<T,R>
    > class c_reg;
    > typedef c_reg<int,std::string> c_my_reg;
    >
    > // also gives error here saying
    > // invlaid use of undefined type c_my_reg
    > template<typename T>
    > class c_reg_init : public c_my_reg
    > {
    > void set_data (int, std::string)
    > }
    >
    > template<typename T> void c_reg_init<T>::set_data(int, std::string)
    > {
    > ...//do something
    > }
    > //end of c_reg_init.h
    >
    > Now as seen above, i'm tyring to avoid inclusion of c_reg.h in
    > c_reg_init header file. But using the forward declaration syntax gives
    > errror mentioned above. It assumes the forward declared template class
    > c_reg to be a struct i dont know why.
    >
    > What i want to basically do is hide the template header file so that i
    > can give the user a interface. In this interface i should be able to
    > just forward declare the template class
    > Is there a way around?


    If you need generic class, you have to give to user whole
    implementation. You can split it into 2 headers, one contains only
    declaration of templated class and second contains full implementation,
    so you can speed up compilation simillary as with #include <iosfwd> and
    #include <iostream>
    Ondra Holub, Jan 8, 2007
    #2
    1. Advertising

  3. Hunk

    Hunk Guest

    Ondra Holub wrote:
    > Hunk napsal:
    > Well, you do not need it, if you want to declare pointer or reference
    > to my_class. But if you need to access any method (or attribute) of
    > this class, you need the definition of this class as well as in case
    > you need to declare instance of this class.
    >
    > It is the same as in following example without templates:
    > class X;
    >
    > X& rx; // OK
    > X* px; // OK
    > X x; // Error
    >
    > void X::method() // Error - nothing is known about methods of class X
    > {
    > }
    >
    > If you need generic class, you have to give to user whole
    > implementation. You can split it into 2 headers, one contains only
    > declaration of templated class and second contains full implementation,
    > so you can speed up compilation simillary as with #include <iosfwd> and
    > #include <iostream>


    So there's no way other than to include the header file which contains
    the declaration?
    That means I would have to necessarily include the declaration header
    file , and using forward declaration has no effect except for use as
    pointers. The methods cannot be accessed for a template class? Is there
    any method people have to hide the template declarations?
    Hunk, Jan 9, 2007
    #3
  4. Hunk

    Axter Guest

    Hunk wrote:
    > Ondra Holub wrote:
    > > Hunk napsal:
    > > Well, you do not need it, if you want to declare pointer or reference
    > > to my_class. But if you need to access any method (or attribute) of
    > > this class, you need the definition of this class as well as in case
    > > you need to declare instance of this class.
    > >
    > > It is the same as in following example without templates:
    > > class X;
    > >
    > > X& rx; // OK
    > > X* px; // OK
    > > X x; // Error
    > >
    > > void X::method() // Error - nothing is known about methods of class X
    > > {
    > > }
    > >
    > > If you need generic class, you have to give to user whole
    > > implementation. You can split it into 2 headers, one contains only
    > > declaration of templated class and second contains full implementation,
    > > so you can speed up compilation simillary as with #include <iosfwd> and
    > > #include <iostream>

    >
    > So there's no way other than to include the header file which contains
    > the declaration?
    > That means I would have to necessarily include the declaration header
    > file , and using forward declaration has no effect except for use as
    > pointers. The methods cannot be accessed for a template class? Is there
    > any method people have to hide the template declarations?


    Template class forward declarations are normally in a source file, and
    not placed in a header.
    If done properly, you can put your template source code in the *.cpp
    source file.
    Template class forward declaration method limits the available types
    that can be used with the template. From looking at your code, this
    seems to be acceptable for your requirements.

    Here's an example usage:

    //c_reg.h
    /////////////////////////////////////////////////////////////////////////////////////
    #include <string>

    template<typename T,typename R>
    class c_reg
    {
    public:
    virtual R get_data(T p_data);
    virtual void set_data(T , R);
    };

    typedef c_reg<int,std::string> c_my_reg; //This is NOT a forward
    template declaration
    /////////////////////////////////////////////////////////////////////////////////////
    //end of c_reg.h

    /c_reg.cpp
    /////////////////////////////////////////////////////////////////////////////////////
    #include <iostream>

    #include "c_reg.h"

    //*****************************
    template c_reg<int,std::string>; //This IS a template class forward
    declaration!!!
    //*****************************

    template<typename T,typename R> R c_reg<T,R>::get_data(T p_data)
    {
    return R();
    }

    template <typename T,typename R> void c_reg<T,R>::set_data(T p_key, R
    p_data)
    {
    std::cout << "c_reg<T,R>::set_data " << p_key << ":" << p_data <<
    std::endl;
    }
    /////////////////////////////////////////////////////////////////////////////////////
    //end of c_reg.cpp


    //c_reg_init.h
    /////////////////////////////////////////////////////////////////////////////////////
    #include "c_reg.h"

    #include <iostream>

    template<typename T>
    class c_reg_init : public c_my_reg
    {
    public:
    void set_data (int, std::string);
    };

    template<typename T> void c_reg_init<T>::set_data(int i, std::string s)

    {
    std::cout << "c_reg_init<T>::set_data " << i << ":" << s <<
    std::endl;
    c_my_reg::set_data(i, s);
    }
    /////////////////////////////////////////////////////////////////////////////////////
    //end of c_reg_init.h


    //main.cpp
    /////////////////////////////////////////////////////////////////////////////////////
    #include "c_reg_init.h"

    int main(int, char**)
    {

    c_reg_init<long> my_c_reg_init;

    my_c_reg_init.set_data(3, "4");

    c_my_reg * pc_my_reg = &my_c_reg_init;
    pc_my_reg->set_data(5, "6");

    return 0;
    }
    /////////////////////////////////////////////////////////////////////////////////////
    //end of main.cpp
    Axter, Jan 9, 2007
    #4
  5. Hunk

    Guest

    Hunk wrote:
    > Hi
    >
    > I have a question on usage of forward declarations of templates. While
    > searching through this group , people suggested using forward
    > declarations and typedefs for templates as
    >
    > // in myfile.h
    > template<typename T,typename R>
    > class some_class;
    >
    > typedef some_class<int,float> my_class;
    >
    > then use my_class as an instance in the program. The advantage in this
    >

    You cannot use forward declaration for base class and it as nothing to
    do with templates. If you have class B that class D derived from it you
    must include class B H file in class D H file since the complier needs
    to know the full declaration of the base class for the derived class.
    This is true also for members in the class that are not pointers or
    reference and for any function that accept by value or return by value.
    Again it has nothing to do with templates
    , Jan 9, 2007
    #5
  6. Hunk

    Hunk Guest


    >
    > Template class forward declarations are normally in a source file, and
    > not placed in a header.
    > If done properly, you can put your template source code in the *.cpp
    > source file.
    > Template class forward declaration method limits the available types
    > that can be used with the template. From looking at your code, this
    > seems to be acceptable for your requirements.
    >
    > Here's an example usage:
    >
    > //c_reg.h
    > /////////////////////////////////////////////////////////////////////////////////////
    > #include <string>
    >
    > template<typename T,typename R>
    > class c_reg
    > {
    > public:
    > virtual R get_data(T p_data);
    > virtual void set_data(T , R);
    > };
    >
    > typedef c_reg<int,std::string> c_my_reg; //This is NOT a forward
    > template declaration
    > /////////////////////////////////////////////////////////////////////////////////////
    > //end of c_reg.h
    >
    > /c_reg.cpp
    > /////////////////////////////////////////////////////////////////////////////////////
    > #include <iostream>
    >
    > #include "c_reg.h"
    >
    > //*****************************
    > template c_reg<int,std::string>; //This IS a template class forward
    > declaration!!!
    > //*****************************
    >
    > template<typename T,typename R> R c_reg<T,R>::get_data(T p_data)
    > {
    > return R();
    > }
    >
    > template <typename T,typename R> void c_reg<T,R>::set_data(T p_key, R
    > p_data)
    > {
    > std::cout << "c_reg<T,R>::set_data " << p_key << ":" << p_data <<
    > std::endl;
    > }
    > /////////////////////////////////////////////////////////////////////////////////////
    > //end of c_reg.cpp
    >
    >
    > //c_reg_init.h
    > /////////////////////////////////////////////////////////////////////////////////////
    > #include "c_reg.h"
    >
    > #include <iostream>
    >
    > template<typename T>
    > class c_reg_init : public c_my_reg
    > {
    > public:
    > void set_data (int, std::string);
    > };
    >
    > template<typename T> void c_reg_init<T>::set_data(int i, std::string s)
    >
    > {
    > std::cout << "c_reg_init<T>::set_data " << i << ":" << s <<
    > std::endl;
    > c_my_reg::set_data(i, s);
    > }
    > /////////////////////////////////////////////////////////////////////////////////////
    > //end of c_reg_init.h
    >
    >
    > //main.cpp
    > /////////////////////////////////////////////////////////////////////////////////////
    > #include "c_reg_init.h"
    >
    > int main(int, char**)
    > {
    >
    > c_reg_init<long> my_c_reg_init;
    >
    > my_c_reg_init.set_data(3, "4");
    >
    > c_my_reg * pc_my_reg = &my_c_reg_init;
    > pc_my_reg->set_data(5, "6");
    >
    > return 0;
    > }
    > /////////////////////////////////////////////////////////////////////////////////////
    > //end of main.cpp


    Axter, thanks for your response. I have a working model of what you
    mentioned. The thing i was looking forward to is a way of not including
    the header file , i.e in the example," c_reg.h" in c_reg_init.h.
    Basically there is a group of template files and i need to provide an
    interface mechanism to the user to use my class. My objective is not to
    include the header file so as to avoid compilation dependency.I was
    looking at a way to forward declare the template classes instead of
    including the header file. Forward declare c_reg and use it in the
    typedef's to do further things. But i guess this is not possible, for
    the simple reason that if no file includes the header file then it
    would not get the code to generate it at all.. so i thing what i'm
    hoping for is akin to a prepetual m/c
    Hunk, Jan 9, 2007
    #6
  7. Hunk

    Hunk Guest

    wrote:
    > Hunk wrote:
    > > Hi
    > >
    > > I have a question on usage of forward declarations of templates. While
    > > searching through this group , people suggested using forward
    > > declarations and typedefs for templates as
    > >
    > > // in myfile.h
    > > template<typename T,typename R>
    > > class some_class;
    > >
    > > typedef some_class<int,float> my_class;
    > >
    > > then use my_class as an instance in the program. The advantage in this
    > >

    > You cannot use forward declaration for base class and it as nothing to
    > do with templates. If you have class B that class D derived from it you
    > must include class B H file in class D H file since the complier needs
    > to know the full declaration of the base class for the derived class.
    > This is true also for members in the class that are not pointers or
    > reference and for any function that accept by value or return by value.
    > Again it has nothing to do with templates


    Yep got your point here. Working on having the forward declarations in
    a manager interface and then having the manager include these header
    files. The manager interface would be given to the user which will
    essentially implement a singleton. I think this should solve the problem
    Hunk, Jan 9, 2007
    #7
    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. qazmlp
    Replies:
    1
    Views:
    593
    Jonathan Turkanis
    Feb 15, 2004
  2. JKop
    Replies:
    3
    Views:
    467
  3. Markus Dehmann
    Replies:
    6
    Views:
    887
    Andre Dajd
    Nov 1, 2004
  4. Replies:
    14
    Views:
    545
  5. recover
    Replies:
    2
    Views:
    799
    recover
    Jul 25, 2006
Loading...

Share This Page