Click to See Complete Forum and Search --> : template and forward declaration


jflegert
October 3rd, 2002, 01:41 PM
I would like to do a forward declare of a nested class in a template, but can't get the syntax right. For example:

template <class T>
class Y
{
public:
class Z;

Z *z;

void foo();
};

template <class T>
void Y<T>::foo()
{
}

template <class T>
class Y<T>::Z
{
public:
int i;
};


The code is all in the same header.
The foo part compiles ok, but I can't get the Z part.
I am using VC7.

Thank you,
John Flegert

Yves M
October 3rd, 2002, 02:52 PM
Well, putting everything into a cpp file works (VC6) and putting everything into an h file works as well.

What error do you get ?

jflegert
October 3rd, 2002, 03:27 PM
The message was:

error C2065: 'T' : undeclared identifier

on the line: "class Y<T>::Z"

The code compiled OK on VC 6. But when I modified the code as follows, I get a compilation error in VC7 and VC6.

template <class T>
class Y
{
public:
class Z;

Z *z;

void foo();
};

template <class T>
class Y<T>::Z
{
public:
int i;

Z() { i = 0; }
};

template <class T>
void Y<T>::foo()
{
z = new Z;
}

In VC6 the message is:

error C2512: 'Z' : no appropriate default constructor available

on the line that has "z = new Z"

and in VC7 the message is:

error C2065: 'T' : undeclared identifier

on the line "class Y<T>::Z".

Thanks for the help.

Yves M
October 3rd, 2002, 03:51 PM
True.

I wonder whether the compiler implements this though. It might not be a lack of correct syntax...

Let's wait for the gurus ;)

Paul McKenzie
October 3rd, 2002, 03:53 PM
This compiles cleanly on Comeau and C++ Builder 6.0.

template <class T>
class Y
{
public:
class Z;

Z *z;

void foo();
};

template <class T>
class Y<T>::Z
{
public:
int i;

Z() { i = 0; }
};

template <class T>
void Y<T>::foo()
{
z = new Z;
}

int main()
{
Y<int> MyY;
MyY.foo();
}

I would suspect this is another Microsoft compiler deficiency when it comes to templates.

Regards,

Paul McKenzie

Yves M
October 3rd, 2002, 04:07 PM
Didn't have to wait for long :D Thanks Paul :)

ncf
October 3rd, 2002, 04:10 PM
Originally posted by jflegert

template <class T>
class Y
{
public:
class Z;

Z *z;

void foo();
};

template <class T>
class Y<T>::Z
{
public:
int i;

Z() { i = 0; }
};

template <class T>
void Y<T>::foo()
{
z = new Z;
}



Does this help? You declared Z as a template class but Y::z is a pointer to a Z without a template type specifier, as is the "new Z" call. How does the compiler know what kind of Z you want?

This worked for me in VC6. In the header:


template <class T, class S>
class Y
{
public:
template <class S> class Z
{
public:
int i;
Z() {i=0;}
};

Z<S> *z;

void foo();
};

template <class T, class S>
void Y<T,S>::foo()
{
z = new Z<S>;
}



and then in a cpp i was able to say this:

Y<int, float> foo;
foo.foo();


is that what you want? I realise i didnt forward declare Z, but my brain has started hurting (and my build finished) :-) Templates are so much fun.

kakalake
October 3rd, 2002, 07:06 PM
I tried this and it works...


class Z;

template <class T>
class Y
{
public:
Z *z;

void foo();
};

class Z
{
public:
int i;
Z() { i = 1; }
};

template <class T>
void Y<T>::foo()
{
z = new Z();
cout << z->i;
}

int main(int argc, char* argv[])
{
Y<int> test;
test.foo();

return 0;
}

jflegert
October 4th, 2002, 07:06 AM
Paul,

Thank you for trying it on the Comeau compiler.

kakalake,

I wanted Z to be nested.

ncf,

From the original post, I wanted Z to be forward declared. In my original code, if I didn't forward declare Z, it would have compiled.

Everyone,
Thanks for the replies.