geraldCelente
geraldCelente

Reputation: 1005

C++ - invalid use of undefined type ... - declaration of `class

I have classes SuperClass and Subclass, where SubClass is inheriting from SuperClass.

In SuperClass I have a constant property who's values depends on the SubClass using it. Howerver I need it to be declared in SuperClass as there are some other methods in SuperClass using it as well, but I need to initalize it in SubClass as the value of the constant changes depending on the SubClass type instantiated.

From a previous question on SO, I know the best solution to this is using a trait class. However using such a solution would involve massive changes to my code. Therefore, I have chosen the approach here shown.

SuperClass.h

#ifndef SUPERCLASS_H
#define SUPERCLASS_H


#include <string>

template <class T, class P>
class SuperClass
{
      public:

       typedef T type;
       typedef P position;

       static const position NULLPOSITION;

};

#endif

SubClass.h

#ifndef SUBCLASS_H
#define SUBCLASS_H

#include <string>
#include "SuperClass.h"


template <class T>
class SubClass:public SuperClass<T,int>
{

};

template<class T>
const typename SuperClass<T,int>::position SuperClass<T,int>::NULLPOSITION=0;

#endif

main.cpp

#include <cstdlib>
#include <iostream>
#include "SubClass.h"

using namespace std;

int main(int argc, char *argv[])
{
    SubClass<int> subClass;

    system("PAUSE");
    return EXIT_SUCCESS;
}

On compiling I get

invalid use of undefined type `class SuperClass<T, int>

and

declaration of `class SuperClass<T, int>

errors. What might be the issue?

Upvotes: 0

Views: 2029

Answers (2)

jxh
jxh

Reputation: 70402

The problem is your definition of NULLPOSITION. You have declared a static member NULLPOSITION for the template SuperClass, but have not defined it. Instead, you attempt to define the member for a partial explicit instantiation of it. You should delete the partial explicit instantiation definition, and define a regular template class static member definition for NULLPOSITION instead.

To allow subclasses to provide a different initialization value for NULLPOSITION, this can be accomplished via a (perhaps optional) template parameter.

template <class T, class P, P INIT>
class SuperClass
{
public:
    typedef T type;
    typedef P position;
    static const position NULLPOSITION;
};

template<class T, class P, P INIT>
const typename SuperClass<T,P,INIT>::position
    SuperClass<T,P,INIT>::NULLPOSITION = INIT;

template <class T>
class SubClass:public SuperClass<T,int, 0>
{
};

Upvotes: 2

Jason
Jason

Reputation: 409

By specializing the way you are, you are not actually instantiating NULLPOSITION (or POSIZIONENULLA, check your code)

14.7.1.2

in particular, the initialization (and any associated side-effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist

You might want to explicitely define the data member with another class, as in

template<typename P>
class PositionClass
{
    public:
        typedef P position;
        static const position NULLPOSITION;
};
template <typename T, class P>
class SuperClass : public PositionClass<P>
{
    public:
        typedef T type;
};

const PositionClass<int>::position  PositionClass<int>::NULLPOSITION = 0;

Upvotes: 0

Related Questions