Create object on heap when using class templates - c++

I want to do this:
Array<int>* arr = new Array();
But I keep getting an error: Argument list for class "Array" is missing.
Is it not possible to create this on the heap? I haven't seen any code that seems to do this.
I've tried another way as well where I use the code:
Array<int>* arr;
and then tried to print the contents of the array, but it was giving me the error that it hadn't been instantiated yet. If I cannot create it on the heap, how am I suppose to instantiate it dynamically. I don't know what the user will want to put into it, after all.
Here's all my code:
Array.h
#ifndef _ARRAY_H_
#define _ARRAY_H_
#include <cstring> // for size_t definition
/**
* #class Array
*
* Basic implementation of a standard array class for chars.
*/
template <typename T>
class Array
{
public:
/// Type definition of the element type.
typedef T type;
/// Default constructor.
Array (void);
private:
/// Pointer to the actual data.
T* data_;
/// Current size of the array.
size_t cur_size_;
/// Maximum size of the array.
size_t max_size_;
};
#include "Array.inl"
//#include "Array.cpp"
#endif // !defined _ARRAY_H_
Array.cpp
#include <stdexcept> // for std::out_of_bounds exception
#include <iostream>
#include "Array.h"
#define MAX_SIZE_ 20
//
// Array
// Default Constructor
template <typename T>
Array <T>::Array (void)
:data_(new T[MAX_SIZE_]),
cur_size_(0),
max_size_(MAX_SIZE_)
{ }
Array.inl
//
// size
//
template <typename T>
inline
size_t Array <T>::size(void) const
{
return this->cur_size_;
}
//
// max_size
//
template <typename T>
inline
size_t Array <T>::max_size(void) const
{
return this->max_size_;
}
driver.cpp
#include <iostream>
//#include "Array_Base.h"
#include "Array.h"
int main(void)
{
Array<int>* arr = new Array();
std::cout << "Max size of array is: " << arr->max_size() << std::endl;
}

Because the class is a template class, just Array isn't a full type. You need to include the template type. And there's no need for the empty parentheses at the end.
Array<int>* arr = new Array<int>;

Related

Template class does not name a type error, separated definition and declaration for header

I am attempting to create a templated vector class, but upon compilation I am receiving an error of
def.hpp:3:1: error: 'TempVector' does not name a type
I keep referring to reference material and my syntax and handling of the header file declaration and definition (.h and .hpp) seem right to me, but I can not figure out what I am overlooking.
Below is the three files I am working with, thank you.
driver.cpp:
#include <iostream>
#include <string>
#include "dec.h"
using namespace std;
int main() {
TempVector <int> v1;
cout<<"ran successfully"<<endl;
}
dec.h:
#ifndef DEC_H
#define DEC_H
#include <iostream>
#include <utility>
// Declaration of class Vector
template <typename T>
class TempVector {
public:
TempVector ();
private:
T* array;
static const unsigned int spare = 10;
};
#include "def.hpp"
#endif
def.hpp:
template <typename T>
TempVector<T>::TempVector () {
std::cout<<"ran successfully";
}

How to initialize dynamic array in constructor using initializer_ist?

I am trying to initialize the dynamic array in the constructor using initialize_list in C++. How can I achieve this?
#include <cstdlib>
#include <initializer_list>
#include <iostream>
#include <utility>
using namespace std;
class vec {
private:
// Variable to store the number of elements contained in this vec.
size_t elements;
// Pointer to store the address of the dynamically allocated memory.
double *data;
public:
/*
* Constructor to create a vec variable with the contents of 'ilist'.
*/
vec(initializer_list<double> ilist);
}
int main() {
vec x = { 1, 2, 3 }; // should call to the constructor
return 0;
}
initializer_list has size method, it gives you information how many elements must be allocated by new, so it could be:
vec(initializer_list<double> ilist)
{
elements = ilist.size();
data = new double[ ilist.size() ];
std::copy(ilist.begin(),ilist.end(),data);
}
Use a standard std::vector container instead of a raw pointer. std::vector is a wrapper for a dynamic array, and it has a constructor that accepts a std::initializer_list as input.
#include <initializer_list>
#include <iostream>
#include <vector>
using namespace std;
class vec {
private:
vector<double> data;
public:
vec(initializer_list<double> ilist) : data(ilist) {}
};

How to combine array.h, array.cpp and main.cpp files together?

How to combine array.h, array.cpp and main.cpp files together? I am getting an error while compiling main.cpp, that class Array is not declared in scope.
main.cpp:
#include<iostream>
#include "Array.h"
#include "Array.cpp"
using namespace std;
int main(){
Array a;
a.Array();
return EXIT_SUCCESS;
}
Array.h:
#ifndef ARRAY_H_INCLUDED
#define ARRAY_H_INCLUDED
class Array{
private:
int data;// The value or data stored in the node
int ArraySize;//Size of array
int* array;
public:
Array();
};
#endif
Array.cpp:
#include <iostream>
#include <cstdlib>
using namespace std;
#include "Array.h" // user defined header file
Array::Array(){ //initialise array
cout << "Initialising array elements----------------->"<< endl;
for (int i=0; i < 4; i++){
//array[i]= 1;
cout << i << endl;
}
}
ERROR message: invalid use of 'class Array'
The problem you have is that you are attempting to call the constructor of a class on an instance of that class:
Array a;
a.Array();
When you declare a function the same name as a class, you are creating a constructor for that class.
class Array
{
public:
// Default constructor
Array();
// This is a function you can call
void PrintData();
}
You can't call this function though. It's called automatically when you create an object of class Array:
Array a; // This will call Array's constructor
a.PrintData(); // This will call the function PrintData on the object 'a'

Undefined reference when using template [duplicate]

This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 7 years ago.
I have a templated class named DataHandler
#ifndef DATAHANDLER_H
#define DATAHANDLER_H
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <set>
#include "constants.h"
template <typename T>
using Car = std::pair< T, T>;
template <typename T>
using SparseMatrix = std::vector< Car<T> >;
template <class T>
class DataHandler
{
public:
// initializes a new DataHandler only if none has been created,
// otherwise return the living instance
static DataHandler<T>* getInstance()
{
if(!dataHandler)
dataHandler = new DataHandler();
return dataHandler;
}
void readFile();
SparseMatrix<T>* getSparseBlue(){ return &sparseBlue; }
SparseMatrix<T>* getSparseRed(){ return &sparseRed; }
virtual ~DataHandler();
private:
// static DataHandler to ensure only one instance can be created
static DataHandler<T> *dataHandler;
// private constructor to use DataHandler as a Singleton
DataHandler();
int numElem = 0;
int m_rows, m_cols = -1;
#endif // DATAHANDLER_H
The source file is:
#include "data_handler.h"
#include <fstream>
#include <algorithm>
#include <omp.h>
#include <chrono>
using namespace std;
using namespace constants;
// Global static pointer used to ensure a single instance of the class.
template<typename T>
DataHandler<T>* DataHandler<T>::dataHandler = NULL;
template<typename T>
DataHandler<T>::DataHandler()
{
//ctor
}
template<typename T>
DataHandler<T>::~DataHandler()
{
//dtor
}
template<typename T>
void DataHandler<T>::readFile()
{
// do some stuff
}
// Instantiation of relevant templates
template class DataHandler<unsigned char>;
template class DataHandler<unsigned short int>;
In the last two lines I instantiate the templates which I define in main.cpp:
#include <iostream>
#include <chrono>
#include <fstream>
#include <algorithm>
#include "data_handler.h"
#include "dense_traffic_handler.h"
#include "sparse_traffic_handler.h"
#include "constants.h"
using namespace std;
// Check the number of rows/cols to choose between char or short int for the sparse case
bool matrixIsSmall()
{
return true;
}
void integerCase()
{
typedef unsigned char T;
DataHandler<T> *dh = DataHandler<T>::getInstance();
dh->readFile();
DenseTrafficHandler dth(dh); // ****** ERROR HERE *****
}
void charCase()
{
typedef unsigned char T;
DataHandler<T> *dh = DataHandler<T>::getInstance();
dh->readFile();
DenseTrafficHandler dth(dh); // ****** ERROR HERE *****
SparseTrafficHandler<T> sth;
set<unsigned short int> step = dh->getstep();
int currentStep = 0;
set<unsigned short int>::const_iterator stepToSave = step.begin();
}
int main(int argc, char *argv[])
{
if(matrixIsSmall())
charCase();
else
integerCase();
return 0;
}
Compiler gives me an error: undefined reference to DenseTrafficHandler::DenseTrafficHandler<unsigned short>(DataHandler<unsigned short>*)
DenseTrafficHandler header is like that:
#ifndef TRAFFICHANDLER_H
#define TRAFFICHANDLER_H
#include "constants.h"
#include "data_handler.h"
class DenseTrafficHandler
{
public:
template<typename T>
DenseTrafficHandler(DataHandler<T> *dh);
virtual ~DenseTrafficHandler();
private:
int m_cols, m_rows;
char* data;
char ** dense = NULL;
};
#endif // TRAFFICHANDLER_H
DenseTrafficHandler source is:
#include "dense_traffic_handler.h"
using namespace std;
using namespace constants;
template <typename T>
DenseTrafficHandler::DenseTrafficHandler(DataHandler<T> *datah)
{
DataHandler<T> *dh = datah;
dense = dh->getDense();
m_rows = dh->getm_rows();
m_cols = dh->getm_cols();
}
DenseTrafficHandler::~DenseTrafficHandler()
{
//dtor
}
So I have two questions:
Why do I receive this error and how can I manage it?
Is there a way in DataHandler source to not specify
template <typename T>
DataHandler<T>::functionName() for every function? (I mean something like using namespace Datahandler<T>)
You receive this error because compiler did not generate the code for this template type. One of solutions is to tell the compiler to do this explicitly by template instantiation:
add to your DenseTrafficHandler.cpp:
template class DenseTrafficHandler<unsigned short>;
Yes, just implement it in the header file. Reading more about it here.

C++ Templates specialisation char* and Valgrind

I've got a huge problem with memory leaks in my program.
I use Valgrind to check memory leaks and with some changes I got about ~20 errors or ~40 errors, but still I can't eliminate all and don't know how.
And I can't change the code in main function, I must fit to it.
I can't change specialisation to string!
Question is what is a properly way to manage with char* and memory.
Rules:
Main code is unchangable
Don't pack char* in any smart pointers or other types.
Problem
Managing memory with char* with containers.
Is it still possible ?
Or instead of container safer is normally allocated array ?
What is wrong with my destructor for char* ?
My main function:
#include <iostream>
#include "test.h"
#include <vector>
using namespace std;
int main()
{
char * cpt[]={"tab","tab2","tab3"};
test<char*> test1;
test1.addItem(cpt[1]);
char * item=test1.getItem(0);
item[0]='Z';
cout<<item<<endl;
return 0;
}
test.h
#ifndef TEST_H
#define TEST_H
#include <vector>
using namespace std;
template<class T>
class test
{
public:
~test();
void addItem(T element){
elements.push_back(element);
}
T getItem(int i){
return elements[i];
}
vector<T> elements;
};
#endif // TEST_H
test.cpp
#include "test.h"
#include <iostream>
#include <cstring>
using namespace std;
template<>
char * test<char*>::getItem(int i)
{
/*char *nowy=new char(strlen(elements[i])+1);
//strcpy(nowy,elements[i]);
return nowy;
//with above code 39 errorr in Valgrind
*/
return elements[i]; // with this instead of above 19 errors in Valgrind
}
template<>
void test<char*>::addItem(char* element){
char * c= new char( strlen (element)+1);
strcpy(c,element);
elements.push_back(c);
}
template<>
test<char*>:: ~test(){
for( auto v: elements)
delete []v; //with this 20 errors
//delete v; instead of above line 19 errors;
}
You should replace
new char(strlen (element) + 1); // this allocate one char with given initial value
by
new char[strlen (element) + 1]; // array of (uninitialized) char
to allocate array of char.
then you have to call delete [].