views:

196

answers:

3

I'm new to C++, so bear with me. I have a generic class called A. A has a nested class called B. A contains a method called getB(), which is supposed to return a new instance of B. However, I can't get my code to compile. Here's what it looks like:#include

A.h

template <class E>
class A {

public:
    class B {
    public:
        int data;
    };

    B * getB(); 
};

A.cpp

#include "A.h"

template <class E>
A<E>::B * A::getB() {
    return new B();
}

When I try to compile this, I get the following error:

error: expected constructor, destructor, or type conversion before '*' token

Does anybody know what I'm doing wrong?

Thanks,

helixed

UPDATE:

Thanks for the quick replies everyone. I'm still having a little trouble getting this working. After taking the suggestions listed here, I have something like this:

A.h

template <class E>
class A {

public:
    class B {
    public:
        int data;
    };

    B * getB(); 
};

template <class E>
typename A<E>::B * A<E>::getB() {
    return new B();
}

class C {

};

However, when I try to use this from main, I get an error. Here's my main method:

main.cpp

#include "A.h"

int main(int argc, char *argv[])
{
    A<C> *a = new A<C>();
    A<C>::B *b = a.getB();
}

When I try to compile this, I get the following error:

error: request for member 'getB' in 'a', which is of non-class type 'A<C>*'

Thanks again for the quick responses.

helixed

+7  A: 

The compiler isn't smart enough to figure that "B" is a type when "A" is templated. Try using typename.

template <class E>
typename A<E>::B * A<E>::getB() {
    return new B();
}
Stephen
And as Steve Jessop mentioned, keep it in the .h file, not the .cc file.
Stephen
This seemed to fix the original problem. However, I'm still having a little bit of trouble, as I've posted above. Thanks for the help.
helixed
Use: "A<C>::B *b = a->getB();" You need to dereference the "a" pointer.
Stephen
+2  A: 

You need to use typename in your definition to hint to the compiler that B is a type.

template <class E>
typename A<E>::B * A::getB() {
   return new B;
}
Nick Meyer
I see your point. I've moved the definition into the A.h file. Thanks.
helixed
A: 

Answer to the update:

You don't need to new everything in C++, in fact, it would be best if you did not, since then you would have to explicitly delete the memory allocated or use smart pointers.

So, here is your code revised:

template <class E>
class A {

public:
    class B {
    public:
        int data;
    };

    B getB(); // Object, not pointer
};

template <class E>
typename A<E>::B A<E>::getB() {
    return B();
}

#include "A.h"

int main(int argc, char *argv[])
{
    A<C> a = A<C>();
    A<C>::B b = a.getB();
}

If you wish to new the A<C> class, then you need to use the operator-> to invoke methods:

A<C>::B b = a->getB();
Matthieu M.