Reputation: 29
I'm trying to design a template class of type T* which is declared as follows:
template <class T>
class StructParamPublic<T*>
{
.....
protected:
T* m_pData;
};
which can be used for creating a struct like this
StructParamPublic <FloatArrayStruct*> m_pFloatArray;
where
FloatArrayStruct
{
float* pData;
size_t arraySize;
};
However, when I compile this I'm getting an error that says StructParamPublic is not a template type.
If I define the following template class
template <class T>
class StructParamPublic
{
.....
protected:
T m_Data;
};
then this error goes away. For some design consideration I don't want to add the second definition to the framework.
My solution was to come up with something like this
template <class T>
class StructParamPublic
{
.....
protected:
T* m_pData;
};
and it compiled fine.
So my question: Is template <class T> class StructParamPublic
some kind of 'base template class' and template <class T>class StructParamPublic<T*>
some sort of derivation of that class?
Upvotes: 0
Views: 1451
Reputation: 16224
You could do it like this:
template<typename T>
class StructParamPublic;
// ^ This just "forward declares" the class for all possible template values
template<typename U>
class StructParamPublic<U*> {
...
};
// ^ This is a partial specialization of the above class template. It will deduce the type of T from the pointer type that you instantiate the template with
If you do it that way then the syntax StructParamPublic<int*>
will be legal and it will deduce the type T as int
in the template when you use it.
In general when you have template<typename T> class < T::dependent_type > { ... };
you should use a template specialization for it to work the way you expect, and that requires that you make the "primary" template first which is not specialized, even if that primary template doesn't actually do anything (besides make a declaration).
Note also that you don't actually need to use type traits here to enforce the pointer type requirement. In the above code if you try to use it with a non-pointer type, it will just find the primary template only and not find a real definition. If you wanted you could add a static assert in the primary template "missing * in StructParamPublic<...>"
or similar.
Upvotes: 1
Reputation: 218323
template <class T> class StructParamPublic<T*>;
is a specialization of
template <class T> class StructParamPublic;
So for your problem, you have several possibilities:
(partial) specialization
template <class T> class StructParamPublic;
template <class T>
class StructParamPublic<T*>
{
// code
protected:
T* m_pData;
};
StructParamPublic<int>
would lead to an error of undefined class.
or static_assert
template <class T>
class StructParamPublic
{
static_assert(std::is_pointer<T>::type, "type should be a pointer type");
using value_type = typename std::remove_pointer<T>::type;
// code
protected:
T m_pData; // or value_type* m_pData;
};
StructParamPublic<int>
would lead to an clean error thanks to static_assert
.
or change meaning of your parameter as your solution.
template <class T>
class StructParamPublic
{
.....
protected:
T* m_pData;
};
StructParamPublic<int>
is used here whereas previous solution requires StructParamPublic<int*>
.
Upvotes: 1
Reputation: 206737
You don't need to define the second class template. You can just use a forward declaration.
template <class T> class StructParamPublic;
and then you can use
template <class T>
class StructParamPublic<T*>
{
.....
protected:
T* m_pData;
};
Upvotes: 1