Use of class template requires template arguments - c++

Hi I'm still wondering why I'm getting this error message :
Use of class template 'Array' requires template arguments
Header :
#ifndef Array_h
#define Array_h
template< typename T>
class Array
{
public:
Array(int = 5);
Array( const Array &);
const Array &operator=(Array &);
T &operator[](int);
T operator[](int) const;
// getters and setters
int getSize() const;
void setSize(int);
~Array();
private:
int size;
T *ptr;
bool checkRange(int);
};
#endif
CPP file
template< typename T >
const Array &Array< T >::operator=(Array &other)
{
if( &other != this)
{
if( other.getSize != this->size)
{
delete [] ptr;
size = other.getSize;
ptr = new T[size];
}
for ( int i = 0; i < size; i++)
{
ptr[i] = other[i];
}
}
return *this;
}
Problem seems to do with returning a const reference to object.
Thanks.

Before the compiler sees Array<T>::, it doesn't know that you are defining a member of the class template, and therefore you cannot use the injected-class-name Array as shorthand for Array<T>. You'll need to write const Array<T> &.
And you got constness backwards in your assignment operator. It should take a const reference and return a non-const one.
Also, Why can templates only be implemented in the header file?

Related

Receiving Error C2670 in Visual Studios 2019

I've searched throughout my entire code, and there aren't any other issues except for this section. The semicolon at the end of the forward-slashed line is the issue. Is there something I'm missing? Full error message below.
source\repos\Square Matrix\SquareMatrix.cpp(108,27): error C2760: syntax error: unexpected token ';', expected '{'
#pragma once
#include <stdexcept>
#include "SquareMatrix.h"
template<typename T>
class SquareMatrix
{
private:
size_t _size; //will be the size of the array. size_t makes sure i only use nonnegative integers for the size
T **_ptr;
public:
SquareMatrix(); //zero parameter constructor
SquareMatrix(const SquareMatrix& rhs); //copy constructor
~SquareMatrix(); //destructor
SquareMatrix(SquareMatrix&& rhs); //Move Constructor
SquareMatrix& operator=(const SquareMatrix& rhs); //Copy assignment Operator
SquareMatrix& operator=(SquareMatrix&& rhs); //Move Assignment Operator
void resize(size_t new_size);
T& at(int row, int column);
size_t size() const;
};
template<typename T>
void SquareMatrix<T>::resize(size_t new_size)
{
std::cout << "Input size of the new matrix: " << std::endl;
std::cin >> new_size;
for (int i = 0; i < _size; i++)
{
delete[] _ptr[i];
}
if (_ptr != nullptr)
delete[] _ptr;
if (new_size != _size)
{
_ptr = new T * [new_size];
for (int i = 0; i < new_size; i++)
{
// _ptr[i] = T *[new_size]; //
}
}
}
It seems that the issue might be in the declaration of your class SquareMatrix. You have not posted it so I cant tell for sure but I tested your method implementation with a dummy class and I don't get any errors in compilation.
Make sure that your class declaration and method declaration have this syntax:
template<class T>
class SquareMatrix {
T a, b;
public:
void resize(size_t new_size);
};
You can review the section on Class Templates to get some examples and a more through explanation.
http://www.cplusplus.com/doc/oldtutorial/templates/

How to make a template class a data member of another class?

So what I'm trying to do is write a class with a template class as its data member. This is part of my homework.
So far this is what I have:
letter_frequencies.h
#include "ltr_freq_pair.h"
#include "darray.h"
class letter_frequencies
{
private:
darray<letterFrequencyStruct> array;
public:
letter_frequencies();
void outputFrequencies();
};
letter_frequencies.cpp
#include <iostream>
#include "letter_frequencies.h"
letter_frequencies::letter_frequencies()
{}
void letter_frequencies::outputFrequencies()
{
for(int index = 0; index < 26; index ++)
{
std::cout << "\n" << array[index].letter;
std::cout << " " << array[index].frequency;
}
}
Everything compiles, but once I run the program it has this error:
a.out: darray.cpp:44: T& darray<T>::operator[](unsigned int) [with T = letterFrequencyStruct]: Assertion 'index < used' failed.
Abort (core dumped)
The code snippet I'm trying to use for this class is:
//Check if Class Works
letter_frequencies array;
array.outputFrequencies();
Right now, the darray works just fine and the program does exactly what I need it to do, but one of the requirements is to have a class named letter_frequency with a data member darray<structTypename> name, which is why I'm fussing with this in the first place.
Also, how would I make the class call the explicit constructor for the darray? I want to set the size to 26.
darray.h
#ifndef DARRAY_H
#define DARRAY_H
#include <iostream>
template <typename T>
class darray
{
public:
//Constructors
darray();
darray(const darray&);
explicit darray(unsigned);
//Destructor
~darray();
//Constant Members
unsigned size() const {return used;}
unsigned capacity() const {return cap;}
//Modification Members
T& operator [] (unsigned);
void pop_back();
void push_back(const T&);
const T* find(const T&) const;
void resize(unsigned);
//Operators
T& operator = (const darray&);
bool operator == (const darray&) const;
//Friends
template <typename X>
friend std::ostream& operator << (std::ostream& output, const darray<X>& array);
private:
T* arr;
unsigned used, cap;
};
template <typename X>
std::ostream& operator << (std::ostream& output, const darray<X>& array)
{
for(int index = 0; index < array.size; index++)
{
output << index << array[index];
}
return output;
}
#include "darray.cpp"
#endif
As I mentioned before, you'd have to make letter_frequencies constructor like this:
letter_frequencies::letter_frequencies() : array(26) {
}
(so you initialize the array with the necessary number of elements).
BUT: I don't think you should make your own home-grown array when std::vector would be better...

Implementing a copy constructor for a linked list

I am trying to implement a copy constructor for a linked list with c++. Would it be possible to first copy the elements of the linked list in to an array and then make the array[i] = list? (list is taken as a parameter.)
template <typename Type>
Single_list<Type>::Single_list( Single_list<Type> const &list ):
list_head( 0 ),
list_tail( 0 ),
node_count( 0 ) {
// enter your implementation here
for(int i = 0; i < node_count; i++){
*tmp_array = new array[node_count];
tmp_array[i] = list;
}
Sorry in advance, I am new to coding..
Okay here it is:
template <typename Type>
class Single_list {
private:
Single_node<Type> *list_head;
Single_node<Type> *list_tail;
int node_count;
public:
Single_list();
Single_list( Single_list const & );
~Single_list();
// Accessors
int size() const;
bool empty() const;
Type front() const;
Type back() const;
Single_node<Type> *head() const;
Single_node<Type> *tail() const;
int count( Type const & ) const;
// Mutators
void swap( Single_list & );
Single_list &operator = ( Single_list const & );
void push_front( Type const & );
void push_back( Type const & );
Type pop_front();
int erase( Type const & );
// Friends
template <typename T>
friend std::ostream &operator << (std::ostream &, Single_list<T> const&);
};
template <typename Type>
Single_list<Type>::Single_list():
list_head( 0 ),
list_tail( 0 ),
node_count( 0 ) {
// empty constructor
}
template <typename Type>
Single_list<Type>::Single_list( Single_list<Type> const &list ):
list_head( 0 ),
list_tail( 0 ),
node_count( 0 ) {
Single_List<Type> *tmp_ptr = 0;
for(tmp_ptr = head(); tmp_ptr !== 0; tmp_ptr->next()){
//my copy constructor so far..
tmp_ptr->retrieve() = list;
}
}
template <typename Type>
Single_list<Type>::~Single_list() {
Single_list<Type> *tmp_ptr = 0; //temp pointer initialized
for(tmp_ptr = head(); tmp_ptr !==0; tmp_ptr-next()){
//iterate through single_list, then delete
delete tmp_ptr;
}
}
Oh and the operator:
template <typename Type>
Single_list<Type> &Single_list<Type>::operator = (Single_list<Type> const &rhs) {
Single_list<Type> copy( rhs );
swap( copy );
return *this;
If you're doing this to develop your coding skillz, then you may want to study the code that implements std::list<>. Otherwise, you can just use it.
The move constructor and move assignment operator = are already implemented in C++0x and C++11 in the Standard Template Library (STL). You can make use of them (with a compatible compiler) simply by including the appropriate header (#include <list>) and using it.
Here's a simple example to demonstrate:
#include <list>
using namespace std;
int main()
{
list<int> my_list;
for (int i = 0; i < 1000000; ++i) // make a big list
my_list.push_back(i);
list<int> my_copied_list = my_list; // copy the list using the conventional assignment operator (slow)
list<int> my_moved_list = move(my_list); // move the list using the move assignment operator (fast)
}

Overloading operator[] for a template class- c++

just wrote a code for a template array class (I know its not finished yet), and trying to remember how to overload operators (meanwhile without special difficulties...).
Anyway, while thinking of how to implement operator[] I wondered what would happen if the index is outside the boundaries of the array... I'm pretty sure it is not possible for me to return a NULL (because of the return type), right? and if so, what should I return in case the index is out of boundries?
here's the code, most of it is redundant to my question, but it might help anyone who google's operators overloading so I post the complete code...
#ifndef __MYARRAY_H
#define __MYARRAY_H
#include <iostream>
using namespace std;
template <class T>
class MyArray
{
int phisicalSize, logicalSize;
char printDelimiter;
T* arr;
public:
MyArray(int size=10, char printDelimiter=' ');
MyArray(const MyArray& other);
~MyArray() {delete []arr;}
const MyArray& operator=(const MyArray& other);
const MyArray& operator+=(const T& newVal);
T& operator[](int index);
friend ostream& operator<<(ostream& os, const MyArray& ma)
{
for(int i=0; i<ma.logicalSize; i++)
os << ma.arr[i] << ma.printDelimiter;
return os;
}
};
template <class T>
T& MyArray<T>::operator[]( int index )
{
if (index < 0 || index > logicalSize)
{
//do what???
}
return arr[index];
}
template <class T>
const MyArray<T>& MyArray<T>::operator+=( const T& newVal )
{
if (logicalSize < phisicalSize)
{
arr[logicalSize] = newVal;
logicalSize++;
}
return *this;
}
template <class T>
const MyArray<T>& MyArray<T>::operator=( const MyArray<T>& other )
{
if (this != &other)
{
delete []arr;
phisicalSize = other.phisicalSize;
logicalSize = other.logicalSize;
printDelimiter = other.printDelimiter;
arr = new T[phisicalSize];
for(int i=0; i<logicalSize; i++)
arr[i] = other.arr[i];
}
return *this;
}
template <class T>
MyArray<T>::MyArray( const MyArray& other ) : arr(NULL)
{
*this = other;
}
template <class T>
MyArray<T>::MyArray( int size, char printDelimiter ) : phisicalSize(size), logicalSize(0), printDelimiter(printDelimiter)
{
arr = new T[phisicalSize];
}
#endif
operator[] generally does no bounds checking. Most of the standard containers that can have a range utilize a separate function, at(), which is range checked and throws a std::out_of_range exception.
You likely want to implement a const T& operator[] overload, too.

templated code not working while non-templated code works!

I spent several hours, completely stuck when I realized that only the templated version of my code has a bug.
In the following code, when pushing_back elements in the myMap, the original vectors myVec1 and myVec2 are modified and contain garbage at the end of the execution. If I un-template everything, just replacing template<T> by double, then the code works fine as I would expect (the original arrays are untouched).
The funny thing is if I put a cout in the copy constructor, it does not get called if the code is templated. But it gets called if I replace the copy constructor with Vector<T2> by the original type Vector<T>, and then everything work fine.
Why wouldn't the compiler know that T2==T since I only use double?
(note, the code has been made as short as possible so as to show the errors - I thus removed accessors, made everything public etc.).
#include <vector>
#include <map>
template<class T>
class Vector{
public:
Vector():n(0),data(0){};
Vector(int N):n(N),data(new T[N]){};
Vector(T x, T y):n(2),data(new T[2]){data[0]=x; data[1]=y;};
template<class T2> Vector(const Vector<T2>& rhs):n(rhs.n), data(new T[n])
{
for (int i=0; i<n; i++)
data[i] = T(rhs.data[i]);
}
~Vector(){delete[] data;}
Vector& operator=(const Vector& rhs)
{
if (rhs.n != n)
{
if (data)
delete[] data;
data = new T[rhs.n];
}
n = rhs.n;
memcpy(data, rhs.data, n*sizeof(T));
return *this;
}
T& operator[](int i){return data[i];}
const T& operator[](int i) const {return data[i];}
int n;
T* data;
};
typedef Vector<double> Vectord;
template <class T> inline bool operator<(const Vector<T>& v1, const Vector<T>& v2)
{
for (int i=0; i<v1.n; i++)
{
if (v1[i]<v2[i]) return true;
if (v1[i]>v2[i]) return false;
}
return false;
}
int main(int argc, char** argv)
{
std::vector<Vectord> myVec1(3);
myVec1[0] = Vectord(1.,3.);
myVec1[1] = Vectord(3.,3.);
myVec1[2] = Vectord(1.,5.);
std::vector<Vectord> myVec2(3);
myVec2[0] = Vectord(4.,1.);
myVec2[1] = Vectord(2.,5.);
myVec2[2] = Vectord(6.,5.);
std::map<Vectord, std::vector<Vectord> > myMap;
for (int i=0; i<3; i++)
{
myMap[myVec1[i]].push_back(myVec2[i]);
}
return 0;
}
A templated constructor is never a copy constructor.
So your class is using the automatically generated copy constructor.
Cheers & hth.,