creating an array of a given template (c++) - c++

lately in my object oriented programming class we were dealing with templates.
in a question we got, we were asked to create a Queue class that can store any type
now my problem start when i want to store an array of somesort in this queue, for example:
Queue < char* >
now when i want to insert a new "node" to the queue i dont want to create a double pointing to a memory block. so basicly my question is: "how can i create an array of the same type of what the template class is pointing at?"
template<class T>
void Queue::enQueue(const T& value, int size = 1)
{
//exeptions handaling...
//handaling the case in wich the template is a pointer
if( _Is_pointer<T>() == true )
{
T temp = new T[size]; // i know its a mistake but thats what i basicly mean to do
for(int i = 0; i < size; i++)
temp[i] = value[i];
m_arr[++m_occupied] = temp; // m_arr is a data member of the T objects, m_occupied is as the name suggest
}
//...
}
thanks for the help :)

You could make template argument deduction work for you
// handling the case in wich the template is a pointer
template <class T> void Queue::enQueue(T const* value, int size = 1) {
This way, the overload deduces T as the type of object that value points at.
Now, you probably want to std::vector because you cannot treat arrays as simple values. Also, the use of new and delete for this kind of task is a code smell.
Guideline: In modern c++, vector<> is the default container for dynamically sized arrays, array<> for fixed-size arrays.
// handling the case in wich the template is a pointer
template <class T> void Queue::enQueue(T const* value, int size = 1) {
m_arr[++m_occupied] = temp(value, value + size);
}
BONUS You can even deduce arrays with size, if you're passing true references to arrays:
// handling the case in wich the template is an array reference
template <class T, size_t Size> void Queue::enQueue(T const (&value)[Size]) {
m_arr[++m_occupied] = std::vector<T>(value, value + Size);
}

Related

Implementing List class with using Stack class

I'm trying to write a Interpreted programming language like Python, so i need a List class for storing 'address of' functions and variables. I'm implemented Stack class for implementing List class:
typedef unsigned int UIntegerP; //This type for storing addresses
#define Free 0x0
template <typename T> class Stack{
public:
unsigned long UsedBSize; // You can use that like End Of Stack (EOS)
Stack(void){
this->BSize = 0; this->UsedBSize = 0;
this->Buffer = new T;
}
~Stack(void){
delete this->Buffer;
}
inline void Push(T Variable){
if(this->UsedBSize == this->BSize){
this->BSize++;
} this->Buffer[this->UsedBSize] = Variable; this->UsedBSize++;
}
inline T Pop(bool IsProtected = false){
if(IsProtected){
return this->Buffer[this->UsedBSize];
}else{
this->UsedBSize--; T Element = this->Buffer[this->UsedBSize]; this->Buffer[this->UsedBSize] = Free;
return Element;
}
}
private:
T *Buffer;
unsigned long BSize;
};
And this is the class i want to implement:
class List{
private:
Stack<UIntegerP> *stack = new Stack<UIntegerP>; //A stack for storing variable addresses
public:
~List(void){
delete this->stack;
}
List(Stack<UIntegerP> Elements){
while(Elements.UsedBSize != 0){
this->stack->Push(Elements.Pop());
}
}
List(Stack<UIntegerP> *Elements){
while(Elements->UsedBSize != 0){
this->stack->Push(Elements->Pop());
}
}
UIntegerP Get(unsigned long Size); //Get Address with Index number
UIntegerP Set(unsigned long Size, UIntegerP Address); //Set Address with Index number
};
I will use this List class for implementing Python like dictionaries. UIntegerP type is required for Variable class. How i can implement this two functions?
Assuming your stack exposes only the Push and Pop functions, then you can't efficiently implement list with indexing on top of that.
If you're programming in normal C++ style, then the basic data structure would be a dynamic array or a linked list. You can then build a stack on top of those. But note that indexing in a linked list is going to be slow (linear time complexity).
If you're programming in a functional style, then the basic structure is "list", which is an immutable singly-linked list and it's effectively the same as immutable stack. But again, indexing with that is going to be slow.
Also note that your Stack is implemented incorrectly: you're allocating memory for a single T, but then you assume you can use that for an unlimited number of Ts. You either need to go the linked list route: allocate a new node for each item and connect the nodes with pointers; or you need to go the dynamic array route: allocate an array of a certain size and when it gets too small, reallocate it.

C++ - Calling the non default constructor in a nested template instantiation

I'm currently working to instantiate an Array of Stacks of cards for a FreeCell implementation. Each of the Array, Stack, and Card classes are created by me, and the Stack and Array classes are templated.
Array<StackRA<Card>> * hometemp = new Array<StackRA<Card>>(4);
When this code runs, it instantiates an Array of size 4, as intended, but calls the default constructor on the Stack, which I need to instantiate to size 13.
I've tried the following:
Array<StackRA<Card>> * hometemp = new Array<StackRA<Card>(13)>(4)
Array<StackRA<Card>> * hometemp = new Array<StackRA<Card>13>(4)
The Stack's default constructor is as follows:
template <typename T>
StackRA<T>::StackRA() : m_stack()
{
size = 0;
}
As well as the 1 arg constructor that I want to call
template <typename T>
StackRA<T>::StackRA( int data ) : m_stack( data )
{
size = data;
}
I've tried my luck on Google, but it keeps leading me to resources on templates inside template classes. Any thoughts are appreciated.
EDIT: Stepping into my program leads to the Array constructor
template<class T>
Array<T>::Array(int length, int start_index)
{
if (length < 0)
{
cout << "Length cannot be negative, length has been defaulted to 0\n";
m_length = 0;
}
else
{
m_length = length;
m_start_index = start_index;
m_array = new T[length];
}
}
The problem, more specifically, is that the "m_array = new T[length];" calls the StackRA default constructor. The question still stands, how can the non default constructor be called. Where in the instantiation would I place the size data I want to pass in?
EDIT2: I've solved this issue for this specific implementation using:
template <typename T>
StackRA<T>::StackRA() : m_stack()
{
size = 13;
}
First, if Array represents an array, and is meant to be used like one, then you don't need to create a pointer. You can construct it as an automatic object:
Array<StackRA<Card>> hometemp(4);
Now the problem as you say is with the following code calling the default-constructor for each element in the array:
m_array = new T[length];
This is true, the default-constructor will be called, initializing each constructor as T(). Prior to C++11, it was not possible to initialize each element using a different constructor, but now you are able to initialize using an initializer-list:
m_array = new T[length] { T(13), T(13), ... };
Of course this wouldn't be preferable for a variable-sized array (or an array with a very large size), and it's not for our purposes. Instead, you can follow the behavior of std::vector and create another constructor that copies an object to each element in the array:
template <typename T>
StackRA<T>::StackRA(int size, const T& obj) : size(size), m_stack(/* ... */)
{
m_array = new T[size];
std::fill(m_array, m_array + size, obj);
}
Now when constructing the array you can pass the correct constructor:
Array<StackRA<Card>> hometemp(4, StackRA<Card>(13));
Is there anything special in your Array so you cannot use std::vector? With std::vector, you would simply say
std::vector<StackRA<Card>> * hometemp =
new std::vector<StackRA<Card>>(4, StackRA<Card>(13));
Better, if the size is always fixed, use std::array, e.g.
std::vector<std::array<Card, 13>> * hometemp =
new std::vector<std::array<Card, 13>>(4);
or
std::array<std::array<Card, 13>, 4> * hometemp =
new std::array<std::array<Card, 13>, 4>();
or even
using Stack = std::array<Card, 13>;
using Deck = std::array<Stack, 4>;
Deck *hometemp = new Deck();
If you want to add functionality, you can simply encapsulate standard library containers into your own types.
Also, you might reconsider your use of the free store and especially raw pointers:
Deck hometemp;
If you insist on your own implementations, you might have a look at std::vector constructors for ideas.

C++ Losing Template Data

I don't consider myself all that knowledgeable in C++ but I'm having a hard time with this concept. So I have a class the holds some template datatype and a double. I want the m_data variable to be generic, but right now I'm only testing with an unsigned int. When I call the function SetData() with say a pointer to an unsigned int I lose the info the pointer is pointing to. This happens when I go out of scope, so I felt I need to do a deep copy of it...
I tried many different constructors and assignment operators but I still lose the info... I feel I'm missing something obvious about templates here.If anyone could point me in the right direction as to why the data is being lost I would be very grateful.
Small bit of code:
template<typename T>
class PointNode {
public:
PointNode(double p){ m_point = p;}
~PointNode();
void SetData(T * data);
T * GetData() const;
private:
double m_point;
T *m_data;
};
template<typename T>
void PointNode::SetData(T * data)
{
m_data = data;
}
template<typename T>
T * PointNode::GetData()
{
return m_Data;
}
OK some more info. This class is being stored in a map that is a member of another class. Heres a bit of it.
template<typename T>
class AuMathPointTreeT
{
public:
//Member Variables
double m_dTolerance;
unsigned int m_cPoint;
map<VectorKey, PointNode<T> > m_tree; /*map posing as a tree */
typename map<VectorKey, PointNode<T> >::iterator iter; /* iterator */
pair< typename map<VectorKey, PointNode<T> >::iterator, bool > return_val;
/* Tree methods */
//constructor
AuMathPointTreeT(double tol);
...
};
In another program I'm using this class, creating node and setting the template data like so
if (node = pnttree.AddPoint(point) )
{
unsigned int * data = new unsigned int();
*data = pntCount;
node->SetData(data);
++pntCount;
}
UPDATE: Ok discovered the culprit of what's wrong, and would like suggestions on how to approach it. When I insert a node into the map class a few functions are called in the process and im losing the original pointer to the newly allocated node class object. Here is what I'm doing.
template<typename T>
PointNode<T> * AuMathPointTreeT<T>::
AddPoint(double point)
{
PointNode<T> * prNode = MakeNode(point);
m_cPoint++;
return prNode;
}
template<typename T>
PointNode<T> * AuMathPointTreeT<T>::
MakeNode(double point)
{
PointNode<T> * prNode = new PointNode<T>;
//set the contents for the node just performs a few calcs on the values
prNode->SetNode(point, m_dTolerance);
//Create the key class using the
VectorKey key(point, m_dTolerance);
//Store the key,node as a pair for easy access
return_val = m_tree.insert( pair<VectorKey, PointNode<T> >(key, *prNode) );
if (return_val.second == false)
prNode = NULL;
unsigned int * test = new unsigned int;
*test = 55;
prNode->SetData(test); //if call this here its no longer the right pointer
return prNode;
}
So after looking at this... I really still want to return a pointer and use it. But maybe the iterator being held by return_val? Im open on suggestions for all aspects too.. Sorry this question has been a mess :\
I don't think this has anything to do with the use of templates. Once a local variable goes out of scope, its location on the stack could be over-written by other data.
If you expect the template class instance to out-live the local variable whose address is passed to SetData, you should consider allocating the data on the heap not the stack. Either way, I'd suggest replacing the raw m_data pointer with an appropriate smart pointer. For example, the use of shared_ptr<> in the template class and its client code should reduce the amount of data copying while at the same time ensuring the data remains valid regardless of whether or not the original data variable is in scope.
If you want a deep copy, you must use T and not T*, or you must do dynamic memory allocation with T* (but it's overkill) and will bring a similar result.
If you really want Nodes of pointers, it will be when you use your Node.
Exemple:
int number = 5;
Node<int*> oneNode(&number); // number will die at end of scope
Node<int> anotherNode(number); //anotherNode can be used without risk
your code will not compile because of your constructor
PointNode(double p){ m_point = p;}
m_point is const, you have to write it to the initializer list:
PointNode(double p) : m_point(p) {}

How to check which derived class your object is with typeid?

So I want to test whether my object is a potion or a weapon. How do I do this with typeid (i.e. or anything for that matter)??
I then want to instantiate an object based on this condition. I cannot just say T temp because that would instantiate an abstract base class (i.e. my Item class has a pure virtual function in it).
template <typename T>
void List<T>::Load(std::ifstream & file)
{
//Read the number of elements
file.read(reinterpret_cast<char *>(&mNumberOfNodes), sizeof(int));
//Insert nodes into list
//If object is a potion
//T * temp = new Potion;
//If object is a weapon
//T * temp = new Weapon;
for( int i = 0; i < mNumberOfNodes; i++ )
{
temp->Load(file);
this->PushFront(&temp);
mNumberOfNodes--;
mNumberOfNodes--;
}
}
I do not recommend using typeid to identify object types in the way you plan on using them. The reason is the values stored in the type information can change between builds. If this happens every data file that was created prior to changing the program will no longer work.
Instead you should define a set of values yourself and associate them with the various object types in your program. the simplest approach is to use an enumeration and a switch/case block to create the objects when you load the file. The example below shows how you might implement your load function using this approach.
enum ObjectType
{
Potion,
Sword,
Condom
};
template <typename T>
void List<T>::Load(std::ifstream & file)
{
//Read the number of elements
file.read(reinterpret_cast<char *>(&mNumberOfNodes), sizeof(int));
//Insert nodes into list
for( int i = 0; i < mNumberOfNodes; i++ )
{
T* obj = NULL;
int nodeType;
file.read(reinterpret_cast<char *>(&nodeType), sizeof(nodeType));
switch(nodeType)
{
case Potion:
obj = new Potion(file);
break;
case Sword:
obj = new Sword(file);
break;
case Condom:
obj = new Trojan(file);
break;
default:
throw std::runtime_error("Invalid object type");
}
PushFront(&obj);
}
}
Depending on your requirements implementing a factory function or class may be more beneficial. This page describes the factory pattern and provides example code (in Java but easily understandable).
I think typeid is sufficient to do this, this website explains how it works http://www.cplusplus.com/reference/typeinfo/type_info/?kw=type_info

C++ Heap Corruption on Delete, Custom List

I'm writing a basic List class. It's backed by an array, not a vector, because we aren't allowed to use vectors.
I seem to be running into heap corruption issues when I call delete[] on my internal backing array.
template <typename T>
void List<T>::Remove( int elementIndex )
{
// Here, I'm creating a new array of one less size to copy all elements over
T* newArray = new T[Count - 1];
bool skippedElement = false;
for (int i = 0; i < Count; i++)
{
if (i == elementIndex)
skippedElement = true;
newArray[i] = array[ skippedElement ? i + 1 : i ];
}
delete[] array; // Heap corruption! See below for definition of array
array = newArray;
Count--;
Capacity--;
}
List.h
class List
{
...
private:
T* array;
...
template <typename T>
List<T>::List( void )
{
array = new T[1];
}
template <typename T>
List<T>::~List( void )
{
delete[] array;
}
}
Does anybody know why this is occuring?
According to this useful post, it says:
"Most heap corruption is caused by (A) calling delete too many times (B) calling the wrong form of delete, or (C) accessing a heap-allocated array out of bounds."
I'm just not sure whether A, B, or/and C are true. Am I calling delete after it's already deleted? I don't think so. I also think I'm calling the right form of delete: delete with brackets. And I sure hope not C.
In your for loop you are iterating Count no of times. But your new array can hold only Count - 1 number of elements. This leads to a heap corruption.