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?
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*>.
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;
};
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.
Related
Is it possible to create a template class inside a template class like the following
// Container.h
template <typename T>
class Container
{
private:
using iterator = Iterator<Node<T>>;
using const_iterator = Iterator<const Node<T>>;
// Node struct to hold data.
template <typename T>
struct Node
{
T data_;
};
public:
// Templated iterator for const or non-const.
template <typename NodeType>
class Iterator
{
private:
NodeType* node_;
public:
Iterator();
};
};
#include "Container.tpp"
So here I declare a template for an iterator that takes in a NodeType which is different from the T that the container class template takes.
If this is possible to do, how do I implemenet the Iterator() inside a different file? Something like
// Container.tpp
template <typename T>
LinkedList<T>::LinkedListIterator<NodeType>::Iterator()
{
// Implementation ...
}
This does not seem right since I do not have access to the NodeType. Any advice would be appreciated.
You should define it as
template <typename T> // for the enclosing class template
template <typename NodeType> // for the member template
Container<T>::Iterator<NodeType>::Iterator()
{
// Implementation ...
}
BTW: The member class template Node can't use the same template parameter name T as the outer class template.
I have the following template class :
template <typename T>
class myClass
{
public:
// Many methods...
protected:
private:
T attribute
// Other attributes.
};
Instantiating an object of type myClass<void> does not work, because of void attribute.
Can you give me some hints to be able to use objects of type myClass<void> without specializing the whole class. Since it has many member functions that rely on the type T, specializing it will lead to code duplication.
Create a templated base class containing attribute, specialize it for void and inherit from it:
namespace detail //Warn end user that he should not use stuff from here
{
template <typename T>
struct myClass_base
{
T attribute;
};
template <>
struct myClass_base<void>
{}; //No attribute at all
}
template <typename T>
class myClass: private detail::myClass_base<T>
{
//rest of definition
};
This would make myClass lack attribute field when instantiating it with type void
You can defer the whole problem by using a custom type and specializing that:
template<typename T>
struct my_type_t
{
using type = T;
};
template<>
struct my_type_t<void>
{};
template<typename T>
using my_type = typename my_type_t<T>::type;
template <typename T>
class myClass
{
public:
// Many methods...
protected:
private:
my_type<T> attribute
// Other attributes.
};
Then at least you don't have to duplicate the whole rest of the class again.
But it probably does not make that much sense, as you surely want to use the type somewhere. So you would have to specialize that places further.
I have a class called node inside another class which is templated. Some of the methods of class Node returns Node pointer. This is an excerpt of how I implemented
template <typename T>
class myClass{
....
class Node{
Node* getNodePointer();
...
}
}
...
template <typename T>
myClass<T>::Node* myClass<T>::Node::getNext()
{ return next; }
When I compile above code, I get this error " myClass.h:138:1: error: need ‘typename’ before ‘myClass::Node’ because ‘myClass’ is a dependent scope". How do I fix this problem? Many thanks
To clarify, the compiler has no idea that myClass<T>::Node is now or ever will be a type. Think of it this way:
template <typename T>
class A
{
public:
typedef T value_type;
};
template <typename T>
class B
{
public:
typename A<T>::value_type x;
};
template <> A<int> { public: static int value_type=10;}
You have to make the promise to the compiler that the type is a typename. It defaults to assuming that it is a value.
How do I fix this problem?
The compiler's error message s pretty clear about this point:
To use nested classes, structs or typedefinitions from a template class you need to add the typename keyword to tell the compiler you want to use it as a type:
template <typename T>
typename myClass<T>::Node* myClass<T>::Node::getNext() { // ...
// ^^^^^^^^ << Add typename keyword
I just updated to GCC 4.8.2 (from 4.7), and am now getting a warning for the following code:
template <class T_base>
class factory {
private:
template <class T>
struct allocator : factory {
// ^ warning: invalid use of incomplete type 'class factory<T_base>'
};
};
To avoid the warning, I tried to define struct allocator outside of factory, but now get the following error:
template <class T_base>
class factory {
private:
template <class T>
struct allocator;
};
template <class T_base, class T>
struct factory<T_base>::allocator<T> : factory<T_base> {
// ^ error: too few template-parameter-lists
};
What am I doing wrong? Is there a syntax for the above construct that avoids both the warning and the error?
You need to spell it like this:
template <class T_base>
template <class T>
struct factory<T_base>::allocator : factory<T_base>
{
// ...
};
The correct syntax for declaring a nested template is to have two separate template argument lists:
template <class T_base>
template <class T>
struct factory<T_base>::allocator : factory<T_base> {
};
However, I’m questioning which semantic sense this piece of code makes.
I'm writing an array class. This array class can contain again arrays as members. When implementing a printing function, I need specializations.
26:template <class T> class array : public vector<T>{
public:
...
string* printToString();
...
};
...
template <class T> string* array<T>::printToString(){
... // generic function
}
template <> inline string* array<double>::printToString(){
... // spezialization for double, works
}
561:template <class U> string* array<array<U>*>::printToString(){
... // does not work
}
The last definition produces
src/core/array.h:561: error: invalid use of incomplete type ‘class array<array<T> >’
src/core/array.h:26: error: declaration of ‘class array<array<T> >’
The g++ version is g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3 if that matters.
Any ideas what's the problem?
Thanks in advance,
Thomas
As an alternative to David's solution, you can unconditionally forward the call to a set of overloaded functions:
template <class T> class array;
namespace details {
template <class T> std::string array_print(array<T> const&);
std::string array_print(array<double> const&); // Regular function
template <class T> std::string array_print(array<array<T> > const&);
}
template <class T> class array : private vector<T> {
public:
...
std::string printToString() { return details::array_print(*this); }
...
};
namespace details { /* implementions after class is defined */ }
You cannot partially specialize a function, you can only fully specialize it, which is the reason why you can provide an specialization for double but not for array<U> where U is a generic type.
You can get around this limitation by using a class template, and partially specializing that, but it will be a bit cumbersome.
namespace detail {
template <typename T>
struct array_printer {
static std::string print( array<T> const & array ) {
// basic implementation
}
};
template <typename T>
struct array_printer< array<T> > {
static std::string print( array< array<T> > const & array ) {
// specialization for array<T>
}
}
}
And then implement the member function as a simple dispatch to the appropriate overload:
template <typename T>
class array : std::vector<T> { // do not publicly derive from STL containers
public:
std::string printToString() const {
return detail::array_printer<T>::print( *this );
}
}
Of course, things are a little more complex in real code, and you will have to order the code appropriatedly, and provide forward declarations of the templates and all that, but this should be enough to get you started.
Your function must be fully specialized. For example:
// Fully specialized. You cannot replace `double` with generic parameter.
template <>
string* array<array<double>*>::printToString(){
return nullptr;
}
However, your class can be partially specialized. For example:
template <class T> class array : public vector<T>{
public:
string* printToString();
};
template <class T> string* array<T>::printToString(){
return nullptr;
};
// Partial specialization.
template <class T> class array<array<T>*> : public vector<T>{
public:
string* printToString();
};
template <class T> string* array<array<T>*>::printToString(){
return nullptr;
};
-- EDIT ---
The methods from generic class will not be automatically "taken" by the class specialization, or vice-versa. You can, however use inheritance to "automate" the reuse of methods from generic class. For example...
template <class T> class array : public vector<T>{
public:
string* printToString();
void f();
};
// (1a)
template <class T> string* array<T>::printToString(){
return nullptr;
};
// (2)
template <class T> void array<T>::f(){
};
template <class T> class array<array<T>*> : public array<T> {
public:
string* printToString();
};
// (1b)
template <class T> string* array<array<T>*>::printToString(){
return nullptr;
};
void Test() {
array<double> a1;
a1.printToString(); // Calls (1a).
a1.f(); // Calls (2).
array<array<char>*> a2;
a2.printToString(); // Calls (1b).
a2.f(); // Calls (2).
}
...which may or may not be what you need (some "manual" repetition might be necessary).