Reputation: 1005
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
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
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