Compiler Error C2106 when trying to simulate a vector - c++

I'm trying to write a fake vector for my class assignment, and I currently get an error in the member function pushBack.
The compiler doesn't seem to like incrementing the SIZE variable which holds the number of elements in the "vector". Is there something I might need to fix?
Your assistance would be highly appreciated for helping me with this, and any other problems you might happen to find.
/*
Write a simple program that simulates the behavior of vectors
-You should be able to add and remove elements to the vector
-You should be able to access an element directly.
-The vector should be able to hold any data type.
*/
#include <stdio.h>
template <class T, int SIZE>
class Vector
{
#pragma region constructors&destructors
private:
T vec[SIZE];
public:
Vector()
{}
~Vector()
{}
#pragma endregion
template <class T/*, int SIZE*/>
void defineVec(T var)
{
for(int i=0; i<SIZE; i++)
{
vec[i] = var;
}
//printf("All elements of the vector have been defined with %", var)
//What should I do when trying to print a data type or variable
//of an unspecified one along with the '%'?
}
template <class T/*, int SIZE*/>
void pushBack(T var)
{
SIZE ++; //C1205
vec[SIZE - 1] = var;
}
template <class T/*, int SIZE*/>
void popBack()
{
vec[SIZE - 1] = NULL;
SIZE--;
}
//template <class T/*, int SIZE*/>
void showElements()
{
for(int i=0; i<SIZE; i++)
{
printf("%d",vec[i]);
printf("\n");
}
}
};
int main()
{
Vector <int, 5> myints;
myints.pushBack(6);
myints.showElements();
return 0;
}

You're passing SIZE as a template parameter. Inside the definition of a template, a non-type template parameter is basically a constant -- i.e., you can't modify it.
You'll need to define a separate variable to keep track of how much of the storage in your vector-alike is currently being used.

Related

Vector of templated objects

I am working on a project that uses templated objects as a vector argument. I must strictly use objects and any primitive types. I'm working on a smaller example to help me grasp the bigger picture.
So far, here is what I have:
#include <iostream>
#include <vector>
using namespace std;
template <class T>
class Thing {
public:
Thing(T type) {
memVar = type;
}
T getMemVar() {
return memVar;
}
private:
T memVar;
};
class U {
public:
U(int i) {
j = i;
}
int getJ () {
return j;
}
private:
int j;
};
int main() {
// your code goes here
vector < Thing <U> > v;
v.push_back(); // idk how to add new elements to this vector.
// I've tried: v.push_back(Thing <U> i(U)),
// v.push_back(U obj(4)), etc etc...
return 0;
}
I don't know how to add elements to this vector.
By example
v.push_back(Thing<U>(4));
If you can compile C++11 or newer, even simpler
v.emplace_back(4)
But, in both cases, you have to modify the constructor of Thing as follows
Thing(T type) : memVar(type) {
}
or add a default constructor in U
U () {
}
because your Thing constructor try to initialize memVar without arguments and next to copy type in memVar

error: Illegal zero sized array

I get this error:
error C2229: class 'GenerateRandNum<int [],int>' has an illegal zero-sized array
In my main, I call my random generator function to input into a empty data set
I call the method in my main like so:
//declare small array
const int smallSize = 20;
int smallArray[smallSize];
// call helper function to put random data in small array
GenerateRandNum <int[], int> genData(smallArray, smallSize);
genData.generate();
Header file
template <class T, class B>
class GenerateRandNum
{
public:
T data;
B size;
GenerateRandNum(T list, B length)
{
data = list;
size = length;
}
void generate();
};
File with method definition
template<class T, class B>
void GenerateRandNum<T, B> ::generate()
{
for (B i = 0; i < size; i++)
{
data[0] = 1 + rand() % size;
}
}
Pointers and arrays are not the same in C/C++. They are two very different things. However, arrays decay into pointers. Most notably in function declarations: The declaration
void foo(int array[7]);
is defined to be equivalent to
void foo(int* array);
That said, all the GenerateRandNum constructor gets, is a int* because that's what T = int [] decays to in the function declaration context. The data member of GenerateRandNum, however, is of type int [] (no decay here), which your compiler assumes to be a zero sized array. Consequently, when you try to assign a pointer to the array, your compiler complains.
You have two options to fix this:
You use an std::vector<> instead, as Marco A. suggests.
You declare your GenerateRandNum class as:
template <class T>
class GenerateRandNum {
public:
T* data;
size_t size;
GenerateRandNum(T* list, size_t length) {
data = list;
size = length;
}
void generate();
};
Note:
I have removed the template parameter for the size type: size_t is guaranteed to be suitable for counting anything in memory, so there is absolutely no point in using anything different. Templating this parameter only obfuscates your code.
There are some problems with your approach:
The first array template parameter can't have its dimension deduced from the argument as n.m. noted, you would need to specify it explicitly:
GenerateRandNum<int[20], int>
There no point in doing
data = list
since in your code sample these are two arrays and you can't assign them directly. You can either copy the memory or specialize your routines/template
You should really consider using a vector of integers, e.g.
template <class T, class B>
class GenerateRandNum
{
public:
T data;
B size;
GenerateRandNum(T list, B length) {
data = list;
size = length;
}
void generate();
};
template<class T, class B>
void GenerateRandNum<T, B> ::generate()
{
srand((unsigned int)time(NULL)); // You should initialize with a seed
for (B i = 0; i < size; i++) {
data[i] = 1 + rand() % size; // I believe you wanted data[i] and not data[0]
}
}
int main(){
//declare small array
const int smallSize = 20;
std::vector<int> smallArray(smallSize);
// call helper function to put random data in small array
GenerateRandNum <std::vector<int>, int> genData(smallArray, smallSize);
genData.generate();
}
Example
I fixed two issues in the code above, take a look at the comments.

How do you create a template definition for a fixed-size array class in C++?

I need to create a template because I don't know what it's an array of. And it needs to be of the size that's passed in the constructor. So here is what I got and I got all sorts of errors. I am a beginner to C++ so any help is appreciated :)
template <typename T, int N>
class Array
{
public:
T& operator[](int index)
{
return data[index];
}
private:
int size;
T *data[N];
};
I think you understand what I'm trying to do. I also need to overload the subscript operator, as you can see. Not sure if I need a reference or a pointer or what. I did have a constructor but it wasn't working properly.
Here's a corrected version with a sample main as well:
#include <iostream>
using namespace std;
template <typename T, int N>
class Array
{
public:
T& operator[](int index)
{
// add check for array index out of bounds i.e. access within 0 to N-1
return data[index];
}
Array() {
data = new T[size = N];
}
~Array() {
if (data)
delete [] data;
}
private:
int size;
T *data;
};
int main(void) {
Array<int, 4> a;
a[0] = 5;
cout << a[0] << endl;
return 0;
}
From what I can see your template is containing an array of pointers, which from what I read and from your [] operator implementation is not what you intend to do. So first you should remove the * from :
T *data[N];
You should probably initialize the size of your template from your constructor, thus you should change :
T *data[N];
to :
T* data;
and :
template <typename T, int N>
to :
template<typename T>
Now that changes the implementation a bit, you should now write a constructor like that :
template<typename T>
Array(int n) {
data = new T[n];
}
and now you should also add a destructor like that :
~Array() {
delete[] data;
}
and there you go :)
However if you want to keep the size as an argument of the template your constructor go like :
template<typename T, int N>
Array() {
}
and the declaration of data :
T data[N];
As said in comments, you may want to use std::array in "real life" conditions, but as a training, implementing your own Array is a good thing to do, that's a training most computer schools do after all.

C++ Generic code for deleting pointer value in Map and vector of pointers

I have some generic code for deleting pointers within a vector or a value of a Map.
Is there a better way of doing this (without using shared_ptrs or any o fthe tr1 extensions )?
Also is the code correct?
Here is my code:
I have a namespace
#ifndef CONTAINERDELETE_H
#define CONTAINERDELETE_H
#include <functional>
#include <map>
#include <vector>
#include <algorithm>
namspace ContainerDelete{
template<class A, class B>
struct DeleteMap
{
bool operator()( pair<A,B> &x) const
{
delete x.second;
return true;
}
};
template<class T>
struct DeleteVector
{
bool operator()(T &x) const
{
delete x;
return true;
}
};
}
#endif
I would then use this namespace in some bit of code to delete a map or vector.
Test Map deletion.
#include "ContainerDelete.h"
using namespace std;
// Test function.
void TestMapDeletion()
{
// Add 10 string to map.
map<int,B*> testMap;
for( int Idx = 0; Idx < 10; ++Idx )
{
testMap[Idx] = new B();
}
// Now delete the map in a single line.
for_each( testMap.begin(),
testMap.end(),
ContainerDelete::DeleteMap<int,B*>());
}
Test Vector Deletion
// Test Function.
void TestVectorDeletion()
{
// Add 10 string to vector.
vector<B*> testVector;
for( int Index = 0; Index < 10; ++Index )
{
testVector.push_back( new B());
}
// Now delete the vector in a single line.
for_each( testVector.begin(),
testVector.end(),
ContainerDelete::DeleteVector<B*>());
}
Thanks,
Mike
Better would be if reduce the genericity as:
struct DeleteVector
{
template<class T> //use the template here!
void operator()(T &x) const
{
delete x;
}
};
if you do so, then you could simply write this:
for_each(testVector.begin(),
testVector.end(),
ContainerDelete::DeleteVector());
No need to pass type argument when you use DeleteVector, for it is not a class template anymore!
Similarly, you can implement DeleteMap functor.
You should also rename DeleteVector to DeleteT, and DeleteMap to DeletePairSecond, as both of these can be used more generically. For example, DeleteT can be used even with std::list, or even with arrays.
The code is ok. I can't imagine any other ways to delete the pointers. All you can do is to reduce explicit type specification like in upper question. I know one more uglier way to do it: functions deduce types of their template parameters. So you can write template function with the first argument - vector, second - ptr and then use std::bind of vector parameter to make this function accepting one parameter - ptr.
But functor is better and more flexible.

How do I return a vector<T> from a function in c++

I am creating a generic data structure and I want to return a vector that contains some of the objects in my structure.
I tried
template<class T>
vector<T> DataStructure<T>::getItems(int count)
{
vector<T> items;
for(int i = 0; i < count; i++)
items.push_back(data[i]);
return items;
}
But the compiler says
error: ISO C++ forbids declaration of 'vector' with no type
error: expected ';' before '<' token
vector is not defined.
You need to #include <vector> and to specify its namespace either using std::vector or putting an using namespace std; in your function or at the global scope (this latter suggestion should be avoided).
#include <vector>
template<class T>
std::vector<T> DataStructure<T>::getItems(int count)
{
std::vector<T> items;
for(int i = 0; i < count; i++)
items.push_back(data[i]);
return items;
}
It's std::vector, not just vector. Other than that,data is undefined in the snippet. But in general, this is the way to return a vector.
As an complement to #etarion perfect answer, the most idiomatic way to perform your operation is, assuming data is of type T*:
template<class T>
std::vector<T> DataStructure<T>::getItems(int count)
{
return std::vector<T>(data, data + count);
}
Since getItems' definition must be available through the header anyway, as it is a method of a class template, it is easiest to define it within the class definition:
template<class T>
struct DataStructure {
std::vector<T> getItems(int count) const {
assert(0 <= count && count <= data.size()); // don't forget to check count
// if you must use op[] with data:
// std::vector<T> items;
// for(int i = 0; i < count; i++)
// items.push_back(data[i]);
// return items;
// if data is a container (using random-access iterators here):
return std::vector<T>(data.begin(), data.begin() + count);
// if data is an array:
// return std::vector<T>(data, data + count);
}
std::vector<T> data; // or is data something else?
};