Help on correct usage of forward declaration of templates

H

Hunk

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?
 
O

Ondra Holub

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>
 
H

Hunk

Ondra said:
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?
 
A

Axter

Hunk said:
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
 
B

boaz1sade

Hunk said:
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
 
H

Hunk

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
 
H

Hunk

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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,053
Latest member
BrodieSola

Latest Threads

Top