简体   繁体   中英

How to have a Struct with template with a class

With this code (just a class of test):

typedef unsigned short UInt16;

template<class T>
class CClass
{
public:
    SValue* getNewSValue(void);
private:
    typedef struct {
        T *mValue;
        T *next;
        T *previous;
        UInt16 index;
    } SValue;
};

template<typename T>
SValue* CClass<T>::getNewSValue(void)
{
    return new SValue;
}

I have the following errors:

error C2143: syntax error : missing ';' before '*'

error C4430: missing type specifier - int assumed. Note: C++ does not support default-int

Is it possible to use a Struct within a class? If I declare the struct out of the class the template doesn't see the template T .

$9.2/2- The key is the below quote from the C++ Standard03

`A class is considered a completely-defined object type (3.9) (or complete type) at the closing } of the class-specifier. Within the class member-specification, the class is regarded as complete within function bodies, default arguments and constructor ctor-initializers (including such things in nested classes). Otherwise it is regarded as incomplete within its own class member-specification.

Don't know what is UINT16 , but the following should work

template<class T> 
class CClass 
{ 
private: 
    typedef struct { 
        T *mValue; 
        T *next; 
        T *previous; 
        short int index;                      // Replacing with int for illustration only
    } SValue; 
public:
    SValue* getNewSValue(void); 
private: 
}; 

EDIT 3: The *** came there trying to make the change BOLD (which I should have deleted anyways)

template<class T> typename CClass<T>::SValue* CClass<T>::getNewSValue(void) 
{ 
    return new SValue; 
}

int main(){
    CClass<int> s;
    s.getNewSValue();
}

Since the member function definition is in global scope, you need to qualify its return type with CClass:: to refer to the name within class scope. Also, the typename keyword is needed when referring to typenames nested within templates.

template<typename T>
typename CClass<T>::SValue* CClass<T>::getNewSValue(void)

Also, the nested struct is unnamed. Note that in C++, classes and structs have proper names, and a typedef name is not a class name. You will be much better off avoiding the typedef.

struct SValue {
    T *mValue;
    T *next;
    T *previous;
    UInt16 index;
};

It looks like your struct is not defined when you declare the return type of getNewSValue .

With that you don't have that error:

template<class T>
class CClass
{
public:
    SValue* getNewSValue(void);
private:
    typedef struct {
        T *mValue;
        T *next;
        T *previous;
        UInt16 index;
    } SValue;
};

template<typename T>
SValue* CClass<T>::getNewSValue(void)
{
  return new SValue;
}

And you also have to qualify the SValue return type, because it is nested in CClass when you use it to define getNewSValue .

Declare SValue before getNewSValue() :

template<class T> 
class CClass 
{ 
private: 
    typedef struct { 
        T *mValue; 
        T *next; 
        T *previous; 
        UInt16 index; 
    } SValue; 
public: 
    SValue* getNewSValue(void); 
}; 

Also, make sure UInt16 is defined.

how about trying this ? it worked on VS2008

template<class T>
class CClass
{
private:
    typedef struct {
        T *mValue;
        T *next;
        T *previous;
        __int16 index;
    } SValue;

public:
    SValue* getNewSValue(void)
    {
        return new SValue;
    }
};

The SValue-Type is inside the CClass-namespace. You need to fully qualify the typename outside the class.

template<typename T>
CClass<T>::SValue* CClass<T>::getNewSValue(void)

Also, you should make SValue public, if it is returned by a public method.

For the record, none of these will compile (on GCC 4.2 at least) as soon as a call to getNewSValue() is called. Since it's a public method that returns a pointer to a private type, you'll get a compile error stating that SValue is private .

In order for this to work, you'll either need to make SValue public, or change the type of the return value of getNewSValue() to something like void* , since it seems you're trying to make SValue an opaque type.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM