How to define a templated subclass of a template? - c++

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.

Related

C++ pointer template specialization

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.

Partially specialize with respect to values in struct given as template parameter

I have a struct which I use as template parameter to configure some classes:
template <int _DIM, class _TYPE>
struct CONFIG{
static constexpr int DIM = _DIM;
using TYPE = _TYPE;
};
I then need to partially specialize a class. I currently do this the following way:
Lines that will instantiate the template:
template <class CONFIG> instantiate(){
Calculator<CONFIG::DIM, typename CONFIG::NODE> calc;
}
The template to specialize:
template <class TYPE>
struct Calculator<2, TYPE>{
static void fct(TYPE t){
}
};
Would there be a way to directly instantiate and specialize Calculator with template parameter of type CONFIG?
Change your instantiation like so:
template <class Config> instantiate(){
Calculator<Config> calc;
}
Then specialize like this:
template <class T>
struct Calculator<CONFIG<2, T>>{
static void fct(T t){
}
};
It's generally a bad idea to overload names like you did for the template parameter CONFIG and the struct CONFIG. Although they are related to you, the compiler treats them very differently.

Need typename error (template related error)

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

Templated Function Pointer in C++

I am facing a problem with templated member function pointer.
The code is as shown below.
#include <String>
#include <iostream>
template<typename T>
struct method_ptr
{
typedef void (T::*Function)(std::string&);
};
template <class T>
class EventHandler
{
private:
method_ptr<T>::Function m_PtrToCapturer;
};
e:\EventHandler.h(13) : error C2146: syntax error : missing ';' before identifier 'm_PtrToCapturer'
I am facing this error.
Even If I use
method_ptr<EventHandler>::Function m_PtrToCapturer;
as member variable I am getting same error as above.
Because method_ptr<T>::Function is a dependent name (dependent on T), you need to disambiguate it with typename:
template <class T>
class EventHandler
{
private:
typename method_ptr<T>::Function m_PtrToCapturer;
// ^^^^^^^^
};
This works,
struct method_ptr
{
typedef void (T::*Function)(std::string&);
};
template <class T>
class EventHandler
{
private:
typename method_ptr<T>::Function m_PtrToCapturer;
};
Since C++11, you can use using.
template <typename T>
using Function = void (T::*)(std::string);
(By the way, why is std::string called-by-value? I recommend const std::string &.)
Aha, I figured out your second question.
template <typename T>
method_ptr<T>::Function m_PtrToMemFunc; //<--
template is only applied to class and function (and cpp11's typedef&using...). you should write like this.
method_ptr<SomeClass>::Function m_PtrToMemFunc;

Question regarding C++ Templates

I used a simple class for a test program about templates, this is what I did:
template <typename T>
class test
{
public:
test<T>::test();
T out();
};
template <typename T>
test<T>::test()
{
}
T test<T>::out()
{
}
int main()
{
//test<int> t;
}
But when I try to compile it says 'T' : undeclared identifier and use of class template requires template argument list , pointing to the same line, where I have implemented the method out() . Can anyone please explain what the problem is?? I'm using visual studio 2008.
Following is more accurate:
template <typename T>
class test
{
public:
test();
T out();
};
template <typename T>
test<T>::test()
{
}
template <typename T>
T test<T>::out()
{
}
1) Don't use <T> inside class
2) Don't forget to declare template <T> before each method declaration out of class body
This line is wrong:
test<T>::test();
Just write this:
test();
Your definition of the out member is missing the template argument list. out should read:-
template <typename T>
T test<T>::out()
{
}