C++ template class self referencing - c++

I am trying to create a class Info<P,S> which holds a pointer to another object of type Info<S,P>. I have the following code.
template <class P, class S>
class Info {
….
public:
Info(…, Info<S,P>* parentInfo) : …, parentInfo(parentInfo)
{}
…
private:
Info<S, P> *parentInfo;
};
….
typedef Info<ActualP, ActualS> OneInfo;
typedef Info<ActualS, ActualP> OtherInfo;
…
OtherInfo* parentInfo =…;
OneInfo info(…, parentInfo);
This is not compiling and saying the constructor is not a valid one (at the call).
I suppose this would cause an infinite recursion while trying to resolve. Am I right? What are the alternatives to implement this intent of referencing Info<S,P> from Info<P,S>?

Use typename to refer a type that depends of a template parameter:
template <class T>
class Info
{
public:
Info() : parentInfo(NULL) {}
Info(Info<typename T> *info) :
parentInfo(info)
{
}
private:
Info<typename T> *parentInfo;
};
int _tmain(int, _TCHAR**)
{
Info<int> parent;
Info<int> child(&parent);
}

Related

how to know the type of another template class in a template class

I have a template class, like this:
template <typename _Tp>
class CLayer{
public:
void AddLayer(CLayer *_layer);
private:
_Tp m_data;
CLayer *m_layer;
};
And then I want to add a double layer to a int layer.
int main()
{
CLayer<double> dlayer;
CLayer<int> ilayer;
ilayer.AddLayer(dlayer); // this expression is wrong;
// here, the AddLayer function is
// void CLayer<int>::AddLayer(CLayer<int> *_layer);
return 0;
}
How to implement that.
I know I can convert type CLayer<double> * to CLayer<int> *, but I will use the data in the future, I have to know the data type is double type.
There is name injection, so your code is:
template <typename T>
class CLayer
{
public:
void AddLayer(CLayer<T>* layer);
private:
T m_data;
CLayer<T>* m_layer;
};
You have to do some changes. Possible solution could be:
template <typename T, typename Next = void>
class CLayer
{
public:
void AddLayer(Next* layer);
private:
T m_data;
Next* m_layer = nullptr;
};
And then
CLayer<double> dlayer;
CLayer<int, CLayer<double>> ilayer;
ilayer.AddLayer(dlayer);
You can't do this since a template type is not a type without a template argument. This implies that CLayer is not an usable type until you specify its template argument, it can't be used alone like you're doing.
To solve your problem without introducing variadic templates you can use inheritance, but this will force you to use the data only from inside the class itself (or provide some hacky mechanics to obtain it), eg:
class CLayer {
public:
void AddLayer(CLayer *_layer);
protected:
CLayer *m_layer;
};
template<typename _Tp>
class CLayerWithData : public CLayer {
protected:
_Tp m_data;
};
CLayer* intLayer = new CLayerWithData<int>();
CLayer* doubleLayer = new CLayerWithData<double>();
doubleLayer->AddLayer(intLayer);

How to define a template of template class

I' ve got a template class :
template <class T>
class A
{
...
protected:
T m_value;
}
And i would like te make a template using this class for vectors:
template <class T>
class B:public A<std::vector<T>> //no need of space between >> (c++11)
{
void testSize()
{
if(m_value.size() > ...)
{
...
}
}
}
The compiler complain about : error: 'm_value' was not declared in this scope
is there a way i can do this or have i to recode this function for each std::vector type using directly the A class?
Thanks,
Edit:
I've tryed this:
template <class T>
class B:public A<std::vector<T>> //no need of space between >> (c++11)
{
void testSize()
{
if(m_value.size() > ...)
{
...
}
}
std::vector<T> m_value;
}
The compiler doesn't complain anymore but does the m_value called in class A function's refer to m_value of class B?
In your first example, m_value is a dependent name.
Just do this to correctly refer it from within B:
this->m_value.size()
That is, turn your if statement to:
if(this->m_value.size() > ...)
The code in the edit section is wrong instead. Class B and class A will refer respectively to their own copy of m_value.

create reference to template virtual class c++

I have such class
template<typename T>
class ConnectionStatus:
{
public:
virtual void setStatus(const T& status) = 0;
virtual T getStatus() = 0;
};
And i want to have a reference to this class in another class, so i do this: ConnectionStatus<typename T>& status; but compiler said error: template argument 1 is invalid. So how i can make a refernce to template virtual class?
Thank you for any help.
There are two main possibilities: when you know what that template argument should be for your class and when you don't.
For the former, it's a simple case of providing it (say it's int in this case):
struct MyClass
{
ConnectionStatus<int> &m_connection_status;
};
If you don't know the argument, make your class a template class:
template <typename ConnectionStatusType>
struct MyClass
{
ConnectionStatus<ConnectionStatusType> &m_connection_status;
};

C++ Derived class

I have a class (Queue) which inherits from a class named Stack.
it goes like this:
template <class T> class Stack
{
public:
virtual const T pop();
LinkedList<T> lst;
};
template <class T> class Queue : public Stack<T>
{
public:
virtual const T pop();
};
template <class T> const T Queue<T>::pop()
{
const T val = lst[0];
return val;
}
The compiler says "lst undecleared"...why?
Because lst is a member of the base class Stack<T> which is a dependent type on T. The compiler can't check dependent types until the template is fully instantiated. You have to let the compiler know that lst is part of such base class by writing Stack<T>::lst.
As its mention in comments, this->lst is also a viable solution. However, people are likely to remove the this as seen unnecessary. Stack<T>::lst seems more explicit in this way.
Try this->lst instead of lst.

Incomplete type as function parameter?

I have that template class that uses a policy for it's output and another template argument to determine the type for it's data members. Furthermore the constructor takes pointers to base classes which are stored in private pointers. Functions of this objects shall take a this pointer to the template class to give them access to the data. In code this looks like this:
class ShapeGenerator;
template <typename PointData, typename OutputPolicy> class ModelCreator {
private:
OutputPolicy output;
ShapeGenerator* shape
std::vector<PointData> data;
public:
ModelCreator (ShapeGenerator *s) : shape(s) { }
void createShape() { shape->generateShape(this); }
};
ShapeGenerator is an interface and shall be implemented. It looks like this:
class ShapeGenerator {
public:
void generateShape (ModelCreator* m) = 0;
};
If I compile this with g++ 4.3.4 (cygwin) I get an error in the ShapeGenerator::generateShape saying 'ModelCreater' is not a type. I put in a forward declaration of ModelCreator but it changed nothing. I played with some combinations of types and parameters, for example passing only the vector and then I got an error message that said something about incomplete types. I guess this is the problem here.
So, is it possible to pass a templated type with without specific arguements? If so, how?
edit:
I'm not bound to the ModelCreator typename. If I have to write it more template-like this isn't problem. But I would like not to specify the types of ModelCreator in the ShapeCreator object. Is that possible?
edit2:
Ok, I guess I was a bit to optimistic with this "design". It would have been nice to just throw in some ingrediences and get a soup. But now the salt has to know about the kind of water in the pot. I'll change the templates to plain old composition. Thanks you guys.
If you want to use the ModelCreator with "free" template parameters, then you have to make ShapeGenerator a template too:
template <typename PointData, typename OutputPolicy>
class ShapeGenerator {
public:
void generateShape (ModelCreator<PointData,OutputPolicy>* m) = 0;
};
or
template <template <typename, typename> class ModelCreator>
class ShapeGenerator {
public:
void generateShape (ModelCreator* m) = 0;
};
The second version takes another template as a parameter. You would use it like this:
ShapeGenerator<ModelCreator<PointDataType,OutPutPolicyType> > shapeGenerator;
You need to make ShapeGenerate a template class as well:
template <typename PointData, typename OutputPolicy>
class ShapeGenerator;
template <typename PointData, typename OutputPolicy>
class ModelCreator {
private:
OutputPolicy output;
ShapeGenerator< PointData, OutputPolicy >* shape;
std::vector<PointData> data;
public:
ModelCreator (ShapeGenerator< PointData, OutputPolicy >* s) : shape(s) { }
void createShape();
};
template <typename PointData, typename OutputPolicy>
class ShapeGenerator {
public:
void generateShape (ModelCreator< PointData, OutputPolicy> * m) = 0;
};
template <typename PointData, typename OutputPolicy>
void ModelCreator< PointData, OutputPolicy >::createShape() { shape->generateShape(this); }