Forward declarations, templates, and typedefs

N

Noah Roberts

I have something like the following:

template<ENUM X, int I = 0>
class Generic
{
....
};

typedef Generic<Val1> v1_type;
typedef Generic<Val2> v2_type;
typedef Generic<Val2, 1> incompat_v2_type;

I'm going to be making this class fundamental to the nature of a rather
large project (the goal is to start using it everywhere instead of
something that is currently done). I don't want to have to include the
header every time I have to return a value of this type. I want to
forward declare in headers and include in source files.

class v1_type; does not work.

I'm not that great with templates and don't fully grasp the subtleties
of what I am trying to accomplish. Can I forward declare this template
and use it? I would prefer to do so based on the typedefs, not the
actual template.
 
V

Victor Bazarov

Noah said:
I have something like the following:

template<ENUM X, int I = 0>
class Generic
{
...
};

typedef Generic<Val1> v1_type;
typedef Generic<Val2> v2_type;
typedef Generic<Val2, 1> incompat_v2_type;

I'm going to be making this class fundamental to the nature of a
rather large project (the goal is to start using it everywhere
instead of something that is currently done). I don't want to have
to include the header every time I have to return a value of this
type. I want to forward declare in headers and include in source
files.

class v1_type; does not work.

I'm not that great with templates and don't fully grasp the subtleties
of what I am trying to accomplish. Can I forward declare this
template and use it? I would prefer to do so based on the typedefs,
not the actual template.

Forward-declaring a template is just like forward-declaring anything
else, you just omit the "{..}" part:

template<ENUM X, int I> class Generic;

(now, I am not sure about the default argument, you might want to give
it a try as well).

As to "using" it, you didn't say what that means.

As to "based on the typedefs", I am not sure what you mean. Please
post more code.

V
 
M

mlimber

Noah said:
I have something like the following:

template<ENUM X, int I = 0>
class Generic
{
...
};

typedef Generic<Val1> v1_type;
typedef Generic<Val2> v2_type;
typedef Generic<Val2, 1> incompat_v2_type;

I'm going to be making this class fundamental to the nature of a rather
large project (the goal is to start using it everywhere instead of
something that is currently done). I don't want to have to include the
header every time I have to return a value of this type. I want to
forward declare in headers and include in source files.

class v1_type; does not work.

I'm not that great with templates and don't fully grasp the subtleties
of what I am trying to accomplish. Can I forward declare this template
and use it? I would prefer to do so based on the typedefs, not the
actual template.

You can't forward-declare a typedef because it is just an alias for
some other type, not a type itself. You can forward declare a class
template as such:

template<class T> class SomeClassTemplate;

But, to forward declare a class template with default parameters, you
have to specify them in the forward declaration:

template<ENUM X, int I = 0> class Generic;

Then you can include perhaps just your typedefs. You'll end up with
something like this:

enum ENUM { A, B };

template<ENUM X, int I = 0> class Generic;

typedef Generic<A> SomeTypeA;
typedef Generic<B> SomeTypeB;
typedef Generic<A,1> SomeTypeBad;

SomeTypeA* pa = 0;
SomeTypeB* pb = 0;
SomeTypeBad* pbad = 0;

template<ENUM X, int I = 0> class Generic
{
public:
enum { val = I };
ENUM foo() const { return X; }
};

Cheers! --M
 
N

Noah Roberts

mlimber said:
You can't forward-declare a typedef because it is just an alias for
some other type, not a type itself. You can forward declare a class
template as such:

template<class T> class SomeClassTemplate;

But, to forward declare a class template with default parameters, you
have to specify them in the forward declaration:

template<ENUM X, int I = 0> class Generic;

Then you can include perhaps just your typedefs. You'll end up with
something like this:

enum ENUM { A, B };

template<ENUM X, int I = 0> class Generic;

typedef Generic<A> SomeTypeA;
typedef Generic<B> SomeTypeB;
typedef Generic<A,1> SomeTypeBad;

SomeTypeA* pa = 0;
SomeTypeB* pb = 0;
SomeTypeBad* pbad = 0;

template<ENUM X, int I = 0> class Generic
{
public:
enum { val = I };
ENUM foo() const { return X; }
};

So actually it might be best to create an "interface" header that had
the forward declaration and the typedefs and include it in the headers
of the clients. Then include the actual definition in sources.

I like templates but getting rid of the compile time dependencies with
them can be tough...
 
M

mlimber

Noah said:
So actually it might be best to create an "interface" header that had
the forward declaration and the typedefs and include it in the headers
of the clients. Then include the actual definition in sources.

If the forward declaration and typedefs are used widely, then sure.
I like templates but getting rid of the compile time dependencies with
them can be tough...

Sometimes it's impossible. For instance, you can't (portably)
forward-declare STL containers such as std::vector since
implementations are permitted to attach as many extra template
parameters as they like, so long as they're given defaults.

Cheers! --M
 
J

Jonathan Mcdougall

mlimber said:
Sometimes it's impossible. For instance, you can't (portably)
forward-declare STL containers such as std::vector since
implementations are permitted to attach as many extra template
parameters as they like, so long as they're given defaults.

Last I heard, that's wrong. See http://tinyurl.com/oestb.


Jonathan
 
B

Bo Persson

mlimber said:
I stand corrected!

Cheers! --M

The real reason you cannot forward declare std::vector is that it has
default template parameters. For some reason, the language doesn't let
you repeat the defaults in both a template definition and a
declaration. So, as long as the std::vector definition contains those
defaults, you cannot write a valid declaration for it.

Note that iosfwd solves this problem for iostreams, but not for any
other std::classes.


Bo Persson
 

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,968
Messages
2,570,153
Members
46,699
Latest member
AnneRosen

Latest Threads

Top