How to have a Struct with template with a class

10,143

Solution 1

$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();
}

Solution 2

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;
};
Share:
10,143
okami
Author by

okami

Updated on June 30, 2022

Comments

  • okami
    okami almost 2 years

    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.

  • Cedric H.
    Cedric H. over 13 years
    What is the purpose of the typename keywork in the definition of getNewSValue ? That's because SValue is unnamed and we have to refer to it using the typedef name ?
  • Johannes Schaub - litb
    Johannes Schaub - litb over 13 years
    @Cedric if we would omit typename, it would be parsed like the definition of a member called SValue of class CClass<T>, for which no type was specified: tempate<class T> Class<T>::SValue;. The tokens following would be junk and rejected by the compiler as syntax errors. This all is because the compiler by default assumes non-types if it can't lookup a name at parse time (i.e it doesn't know what T is yet, so it can't lookup SValue). If you put typename, SValue is correctly regarded as a typename for the member getNewSValue.
  • okami
    okami over 13 years
    The code you put generates the following error: "error C2244: 'CClass<T>::getNewSValue' : unable to match function definition to an existing declaration"
  • okami
    okami over 13 years
    This is very verbose :-), But Potatos your code generates the following err, on the line: typename CClass<T>::SValue* CClass<T>::getNewSValue(void) ERROR ---> "error C2899: typename cannot be used outside a template declaration"
  • Potatoswatter
    Potatoswatter over 13 years
    @okami: keep the template< typename T > part. For less verbose syntax, define the function inside the class {} scope. Then typename and qualification (on class-local types) aren't needed.
  • mukeshkumar
    mukeshkumar over 13 years
    for a while you confused me with the triple pointers (*'s). I think it should be SValue* and not SValue***
  • Chubsdad
    Chubsdad over 13 years
    @hype: Yes, it is my fault. I was trying to make it BOLD and then decided not to do it. So I manually removed the leading ** but forgot the trailing ones :( Have edited my post accordingly
  • daohu527
    daohu527 about 3 years
    Can it be achieved by "decltype" now?