Hello i have this IntArray i want to convert to accept generic types:
class IntArray {
private:
int* first_cell = nullptr;
int size = 0; // currently occupied elements
int capacity = 8; // size of the allocated memory
public:
IntArray() {
first_cell = new int[capacity]; // Declare the array in memory
}
IntArray(const IntArray& src)
: size(src.size),
capacity(src.capacity)
{
first_cell = new int[capacity];
std::copy_n(src.first_cell, size, first_cell);
}
IntArray(IntArray&& src)
: first_cell(src.first_cell),
size(src.size),
capacity(src.capacity)
{
src.first_cell = nullptr;
src.size = src.capacity = 0;
}
~IntArray() {
delete[] first_cell;
}
IntArray& operator=(IntArray rhs) {
IntArray temp(std::move(rhs));
std::swap(first_cell, temp.first_cell);
std::swap(size, temp.size);
std::swap(capacity, temp.capacity);
return *this;
}
void push_back(int number) {
if (size == capacity) {
int new_cap = capacity * 2; // increased capacity
int* new_arr = new int[new_cap]; // new arr with new capacity
for (int k = 0; k < size; ++k) {
new_arr[k] = first_cell[k]; // copy data from frist array
}
delete[] first_cell; // remove first array
first_cell = new_arr;
capacity = new_cap;
}
first_cell[size] = number;
++size;
}
int length() {
return size;
}
int index_of(int number) {
for (int k = 0; k < size; k++) {
if (number == first_cell[k]) {
return k;
}
}
return -1;
}
void print(char symb) {
for (int k = 0; k < size; ++k) {
std::cout << first_cell[k] << symb;
}
}
};
How can i convert this array it to accept any type like generic array? I want to be able to accept any types is this possible? And how do i check the types? If you can point me in the right direction because i have no idea how it can be done? Thanks.
I figured it out;
template<class T>
class List {
private:
T* first_cell = nullptr;
int size = 0; // currently occupied elements
int capacity = 8; // size of the allocated memory
public:
List() {
first_cell = new T[capacity]; // Declare the array in memory
}
List(const List& src)
: size(src.size),
capacity(src.capacity)
{
first_cell = new T[capacity];
std::copy_n(src.first_cell, size, first_cell);
}
List(List&& src)
: first_cell(src.first_cell),
size(src.size),
capacity(src.capacity)
{
src.first_cell = nullptr;
src.size = src.capacity = 0;
}
~List() {
delete[] first_cell;
}
List& operator=(List rhs) {
List temp(std::move(rhs));
std::swap(first_cell, temp.first_cell);
std::swap(size, temp.size);
std::swap(capacity, temp.capacity);
return *this;
}
void push_back(int number) {
if (size == capacity) {
int new_cap = capacity * 2; // increased capacity
T* new_arr = new T[new_cap]; // new arr with new capacity
for (int k = 0; k < size; ++k) {
new_arr[k] = first_cell[k]; // copy data from frist array
}
delete[] first_cell; // remove first array
first_cell = new_arr;
capacity = new_cap;
}
first_cell[size] = number;
++size;
}
int length() {
return size;
}
int first_index_of(int number) {
for (int k = 0; k < size; k++) {
if (number == first_cell[k]) {
return k;
}
}
return -1;
}
void print(char symb) {
for (int k = 0; k < size; ++k) {
std::cout << first_cell[k] << symb;
}
}
};
Related
I'm trying to make an arraylist class where I make a moving Average function in my arraylist class while outputting the moving average of my arraylist class.
I've tried various research and examples online and I've officially hit a wall. Can someone please help me fix my problem. I really need to get this fixed as soon as possible. Code was provided by my professor.
#ifndef ARRAYLIST_H_
#define ARRAYLIST_H_
#include<iostream>
using namespace std;
class arrayList {
int size;
int capacity;
double * p;
void resize() {
capacity *= 2;
double * temp = new double[capacity];
for (int i = 0; i < size; i++) {
temp[i] = p[i];
}
delete[] p;
p = temp;
}
}
public:
arrayList(): size(0), capacity(1) {
p = new double[capacity];
}
arrayList(int cap): size(0), capacity(cap) {
p = new double[capacity];
}
//copy constructor
arrayList(const arrayList & copy) {
size = copy.size;
capacity = copy.capacity;
p = new double[capacity];
for (int i = 0; i < size; ++i)
p[i] = copy.p[i];
}
//move constructor
arrayList(arrayList && move) {
size = move.size;
capacity = move.capacity;
p = move.p;
move.size = 0;
move.capacity = 0;
move.p = nullptr;
}
//copy assignment operator
arrayList & operator = (const arrayList & copyA) {
if (this != & copyA) {
size = copyA.size;
capacity = copyA.capacity;
p = new double[capacity];
for (int i = 0; i < copyA.size; ++i)
p[i] = copyA.p[i];
delete[] p;
}
return *this;
}
// move assignment operator
arrayList & operator = (arrayList moveA) {
if (this != & moveA) {
size = moveA.size;
capacity = moveA.capacity;
delete[] p;
p = moveA.p;
moveA.p = nullptr;
}
return *this;
}
//destructor
~arrayList() {
delete[] p;
}
void insert(int index, int value) {
if (index >= capacity) {
cout << "OUT OF BOUNDS!";
}
if (index < size && index >= 0) {
for (int i = size; i > index; --i) {
p[i] = p[i - 1];
}
p[index] = value;
size++;
} else {
p[index] = value;
size++;
}
}
void append(int val) {
if (size == capacity)
resize();
p[size] = val;
size++;
}
void movingAvg(const arrayList & val, int kernel) {
for (int i = 0; i < val.size; ++i) {
kernel = val.p[i];
val.p[i] = kernel[val.size - 1 - i];
kernel[size - 1 - i] = kernel;
cout << "average of the array is: " << val.p;
}
friend ostream & operator << (ostream & os, arrayList & val) {
for (int i = 0; i < val.size; ++i)
os << val.p[i] << " ";
os << endl << endl;
return os;
}
};
// main.cpp
int main() {
arrayList a;
a.append(45);
cout << a;
a.append(14);
cout << a;
a.insert(2, 76);
cout << a;
//CRASHES AT THIS POINT!
a.insert(3, 45);
cout << a;
a.insert(5, 23);
cout << a;
return 0;
}
OUTPUT:
45
45 14
45 14 76 0
You are deleting p more than once in your resize function. That's likely the source of your crash.
Instead of this:
void resize(){
capacity *= 2; //THIS IS WHAT'S CRASHING THE CODE
double *temp = new double[capacity];
for(int i = 0; i < size; i++){
temp[i] = p[i];
delete []p;
p = temp;
temp = nullptr;
}
}
Implement this:
void resize() {
capacity *= 2;
double *temp = new double[capacity];
for (int i = 0; i < size; i++) {
temp[i] = p[i];
}
delete [] p;
p = temp;
}
And if you want to be more efficient with the copy loop:
void resize() {
capacity *= 2;
double *temp = new double[capacity];
memcpy(temp, p, sizeof(double)*size);
delete [] p;
p = temp;
}
Im trying to implement one of the Vector's Functions which is Resize
As much as I know all the other functions that I implemented are alright
In the test code I tried to print out every possible situation that might happen but when I came to print the size of the new Vector (poitner to integer called _elements)
I get an error "#.exr Triggered a breakpoint
for some odd reason in the tester (main) when i set at the loop "i <8" it works fine but if I do <= it triggers it
I believe the is caused by the resize function but Even after following the debugger I cant seem to find the problem
(explenation of the funtion is in the code)
the vector that I created was successfuly intelized for those who might wonder
Why is this happening?
the function with the following inputs / outputs are:
Vector::Vector(const Vector& other)
{
_elements = new int;
_size = other._size;
_capacity = other._capacity;
_resizeFactor = other._resizeFactor;
for (int i = 0; i < _size; ++i)
{
_elements[i] = other._elements[i];
}
}
//change _size to n, unless n is greater than the vector's capacity
//same as above, if new elements added their value is val
void Vector::resize(int n, const int& val)
{
if (n <= _capacity)
{
while (n < _size)
{
pop_back();
}
while (n > _size)
{
push_back(val);
}
_capacity = n;
}
else if (n > _capacity)
{
reserve(n);
while (n > _size)
{
push_back(val);
}
}
}
//change the capacity
void Vector::reserve(int n)
{
if (n > _capacity)
{
int size = _resizeFactor;
while (n - _capacity > size)
{
size = size + _resizeFactor;
}
_capacity += size;
}
}
//adds element at the end of the vector
void Vector::push_back(const int& val)
{
if (_size < _capacity)
{
_elements[_size] = val;
_size++;
}
else if (_size == _capacity)
{
int* a = new int[_capacity + _resizeFactor];
for (int i = 0; i < _size; i++)
{
a[i] = _elements[i];
}
_capacity += _resizeFactor;
_elements = new int[_capacity];
for (int i = 0; i < _size; i++)
{
_elements[i] = a[i];
}
delete a;
_elements[_size] = val;
_size++;
}
}
void Vector::pop_back()
{
if (_size > 0)
{
_elements[_size] = NULL;
_size--;
}
}
and I check it with
void print(const Vector& p)
{
cout << "Size = " << p.size() << ", Capacity = " << p.capacity() << ", isEmpty = " << (p.empty() ? "True" : "False") << endl;
}
and in main:
Vector a(10);
for (int i = 0; i <= 8; i++)
a.push_back(i+1);
print(a);
a.push_back(10);
print(a);
a.push_back(11);
print(a);
int x = 99;
a.resize(a.capacity() + 11, x);
print(a);
I had this task in C++ where I had to implement a Stack only using arrays (and not using things like Vectors). The teacher gave us an interface to follow and some code to test our ArrayStack on. My problem is that when I create a stack, fill it with 100 elements then empty it the size is 4 (i set 4 for a minimum) and when the teacher code do the same (in the testStack function) the same check fails.
Heres my code:
#include <iostream>
#include <string>
#include <assert.h>
using namespace std;
template<typename T>
class Stack {
public:
// Adds new element to the top of the stack
virtual void push(T x) = 0;
// Returns the top element AND removes it from the stack
// If the stack is empty use 'throw std::out_of_range("<human_friendly_message>");'
virtual T pop() = 0;
// Returns the top element but does NOT remove it from the stack
// If the stack is empty use 'throw std::out_of_range("<human_friendly_message>");'
virtual T top() = 0;
// Returns the current number of elements in the stack
virtual int getSize() = 0;
// Returns the current capacity of the underlying data storage (array)
virtual int getCapacity() = 0;
// Returns true if the stack has no elements and false otherwise
virtual bool isEmpty() = 0;
};
template<typename T>
class ArrayStack : public Stack<T>{
private:
T* data;
int arraysize;
int N;
void resize(int capacity)
{
T* copy = new T[capacity];
for (int i = 0; i < N; i++)
copy[i] = data[i];
T* p = data;
data = copy;
delete [] p;
}
public:
ArrayStack(){
N = 0;
data = new T[4];
arraysize = 4;
}
ArrayStack(int n){
if (n < 1) n = 1;
N = 0;
data = new T[n];
arraysize = n;
}
bool isEmpty(){ return N == 0; }
void push(T x)
{
if (N == arraysize)
{
resize(2 * arraysize);
arraysize *= 2;
}
data[N] = x;
N++;
}
T pop()
{
if (isEmpty()){
throw out_of_range("Can't pop on empty stack");
}
else{
N--;
T k;
k = data[N];
if (N > 0 && N == arraysize / 4 && arraysize/2>=4)
{
resize(arraysize / 2);
arraysize /= 2;
}
return k;
}
}
T top()
{
if (isEmpty()) throw out_of_range("Can't top on empty stack");
return data[N - 1];
}
int getCapacity()
{
return arraysize;
}
int getSize()
{
return N;
}
~ArrayStack()
{
delete [] data;
}
};
template<class T>
void testStack(Stack<T> *& stack, int cap = 128) {
for (int i = 0; i < 100; i++) {
stack->push(i);
assert(stack->top() == i);
}
assert(stack->getCapacity() == cap);
assert(stack->getSize() == 100);
for (int i = 99; i >= 0; i--) {
assert(stack->top() == i);
stack->pop();
}
assert(stack->getCapacity() == 4);
assert(stack->isEmpty());
}
int main() {
try {
Stack<int> * stackI = new ArrayStack<int>();
testStack(stackI);
delete stackI;
Stack<float> * stackF = new ArrayStack<float>(1);
testStack(stackF);
delete stackF;
Stack<double> * stackD = new ArrayStack<double>(65536);
testStack(stackD, 65536);
delete stackD;
Stack<string> * stackS = new ArrayStack<string>();
stackS->push("string1");
stackS->push("string2");
stackS->push("string3");
stackS->push("string4");
for (int i = 0; i < 4; i++) {
stackS->pop();
}
assert(stackS->isEmpty());
cout << "All tests passed!" << endl;
}
catch (std::exception & ex) {
cout << ex.what() << endl;
}
return 0;
}
As you may have noticed, the problem occurs with the last stack, the one with an initial capacity of 65536.
If you print the capacity just before the failed assertion, you will notice that it's 65536.
It looks like the stack hasn't been resized at all.
Looking at your conditions for when to shrink the storage, there is a required condition that N == arraysize / 4.
Since N doesn't become greater than 100, and 65536 / 4 is 16384, this condition will never be true.
Replacing == with <= takes care of it:
N <= arraysize / 4
I have to replicate a vector class using an int and overload a bunch of operators. How ever every time I try to use the +, -, or / operator I get a runtime error which says invalid allocation size: 4294967295 bytes. Any feed back on how I can improve my code is welcome as well.
my code:
myArray.h
#include<iostream>
using namespace std;
class myArray{
private:
int *A;
int lenght;
int maxSize;
public:
myArray(){lenght = 0; maxSize = 0; A = new int[maxSize];}
myArray(int s){maxSize = s; lenght = 0; A = new int[maxSize];}
myArray(const myArray &M);
~myArray(){delete[] A;}
const int getMaxSize(){return maxSize;}
const int getLenght(){return lenght;}
const myArray& operator +(const myArray& A);
const myArray& operator -(const myArray A);
const int operator *(const myArray& A);
const myArray& operator /(const myArray A);
const myArray& operator +(int A);
const myArray& operator -(int A);
const int operator *(int A);
const myArray operator /(int A);
const myArray operator ++();
const myArray operator ++(int);
const myArray operator --();
const myArray operator --(int);
myArray operator -();
int operator [](int ind) const;
myArray& operator =(const myArray& rho);
void push(int n);
int pop();
void insert(int n, int pos);
int remove(int pos);
void resize(int newSize);
};
myException.h
#include<iostream>
#include<exception>
#include<string>
using namespace std;
class myException: public exception
{
private:
int code;
string reason;
public:
myException(){code = 0; reason = "Unknown";}
myException(int c, string r){code = c; reason = r;}
friend ostream& operator <<(ostream& outputStream, const myException A);
};
ostream& operator <<(ostream& outputStream, const myException A)
{
outputStream << "Code: " << A.code << " Reason: " << A.reason << endl;
return outputStream;
}
myArray.cpp
#ifndef MYARRAY_H
#define MYARRAY_H
#include "myArray.h"
#include "myException.h"
//Copy contructor
myArray::myArray(const myArray &M)
{
maxSize = M.maxSize;
lenght = M.lenght;
A = new int[maxSize];
for(int i = 0; i < M.lenght; i++)
A[i] = M.A[i];
}
//Adds the elements of the array with each other and returns the result
const myArray& myArray::operator +(const myArray& secondArray)
{
try
{
if(lenght != secondArray.lenght)
throw myException(10, "Different sizes!");
myArray result(secondArray);
for(int i = 0; i < lenght;i++)
result.A[i] = A[i] + secondArray.A[i];
return result;
}
catch(myException& e)
{
cout << e;
}
}
//Subtracts the elements of the array with each other and returns the result
const myArray& myArray::operator -(const myArray secondArray)
{
try
{
if(lenght != secondArray.lenght)
throw myException(10, "Different sizes!");
myArray result(secondArray);
for(int i = 0; i < lenght;i++)
result.A[i] = this->A[i] - secondArray.A[i];
return result;
}
catch(myException& e)
{
cout << e;
}
}
//Gets the dot product of 2 vectors
const int myArray::operator *(const myArray& secondArray)
{
try
{
if(lenght != secondArray.lenght)
throw myException(10, "Different sizes!");
int result = 0;
for(int i = 0; i < lenght;i++)
result += this->A[i] * secondArray.A[i];
return result;
}
catch(myException& e)
{
cout << e;
}
}
//Divides the elements of the array with each other and returns the result
const myArray& myArray::operator /(const myArray secondArray)
{
try
{
if(lenght != secondArray.lenght)
throw myException(10, "Different sizes!");
myArray result(secondArray);
for(int i = 0; i < lenght;i++)
result.A[i] = this->A[i] / secondArray.A[i];
return result;
}
catch(myException& e)
{
cout << e;
}
}
//Adds the elements of the array with an int and returns the result
const myArray& myArray::operator +(int A)
{
myArray result(*this);
for(int i = 0; i < lenght;i++)
result = this->A[i] + A;
return result;
}
//Subtracts the elements of the array with an int and returns the result
const myArray& myArray::operator -(int A)
{
myArray result(*this);
for(int i = 0; i < lenght;i++)
result = this->A[i] - A;
return result;
}
//Gets the dot product of a vector multiplied by an int
const int myArray::operator *(int A)
{
int result = 0;
for(int i = 0; i < lenght;i++)
result += this->A[i] * A;
return result;
}
//Divides the elements of the array with an int and returns the result
const myArray myArray::operator /(int A)
{
myArray result(*this);
for(int i = 0; i < lenght;i++)
result = this->A[i] / A;
return result;
}
//increments every element in the array by 1(Pre-increment)
const myArray myArray::operator ++()
{
for(int i = 0; i < lenght; i++)
++A[i];
return *this;
}
//increments every element in the array by 1(Post-increment)
const myArray myArray::operator ++(int)
{
myArray temp(maxSize);
for(int i = 0; i < lenght; i++)
temp.A[i] = A[i]++;
return temp;
}
//decrements every element in the array by 1(Pre-decrement)
const myArray myArray::operator --()
{
for(int i = 0; i < lenght; i++)
--A[i];
return *this;
}
//decrements every element in the array by 1(Post-decrement)
const myArray myArray::operator --(int)
{
myArray temp(maxSize);
for(int i = 0; i < lenght; i++)
temp.A[i] = A[i]--;
return temp;
}
//Makes every element in the array negative
myArray myArray::operator -()
{
for(int i = 0; i < lenght; i++)
A[i] = -A[i];
return *this;
}
//returns the number in the array using []
int myArray::operator [](int ind) const
{
try
{
if(ind > lenght)
throw myException(60, "Array index out of bounds");
return A[ind];
}
catch(myException& e)
{
cout << e;
}
}
//Assignment operator
myArray& myArray::operator=(const myArray& B)
{
delete [] A;
A = new int[B.maxSize];
lenght = B.lenght;
maxSize = B.maxSize;
for(int i = 0; i < B.lenght; i++)
{
A[i] = B.A[i];
}
return (*this);
}
//pushes the value inserted to the next available spot in the array
void myArray::push(int n)
{
try
{
if(lenght == maxSize)
throw myException(30, "Not enough space");
if(lenght == 0)
{
A[0] = n;
lenght++;
}
else
{
for(int i = 0; i < lenght; i++)
{
if(i+1 == lenght)
{
A[i+1] = n;
lenght++;
break;
}
}
}
}
catch(myException& e)
{
cout << e;
}
}
//Removes the last element in the array and returns it
int myArray::pop()
{
try
{
if(lenght <= 0)
throw myException(60, "Array index out of bounds");
int temp = A[lenght - 1];
A[lenght - 1] = NULL;
lenght--;
return temp;
}
catch(myException& e)
{
cout << e;
}
}
inserts an element at the specified position
void myArray::insert(int n, int pos)
{
try
{
if(pos > lenght)
throw myException(60, "Array index out of bounds");
for(int i = 0; i <= lenght; i++)
{
if(i == pos)
{
A[i-1] = n;
}
}
}
catch(myException& e)
{
cout << e;
}
}
//removes an element at a specified position an returns the value.
int myArray::remove(int pos)
{
try
{
if(pos < 0 || (pos > lenght -1))
throw myException(50, "Invalid Position");
int temp = A[pos];
A[pos] = NULL;
for(int i = pos; i < lenght; i++)
{
A[i] = A[i+1];
}
return temp;
}
catch(myException& e)
{
cout << e;
}
}
//Re sizes the entire array
void myArray::resize(int newSize)
{
int *B;
B = new int[newSize];
maxSize = newSize;
for(int i = 0; i < lenght; i++)
B[i] = A[i];
delete[] A;
A = B;
}
#endif
This is just a dummy main to test everything on the myArray class
main.cpp
#include "myArray.h"
int main()
{
int num;
myArray vector1;
myArray vector2(5);
myArray vector3;
vector1.resize(5);
//cout << "Max Size: " << vector1.getMaxSize() << endl;
for(int i = 0; i < 4; i++)
{
cin >> num;
vector1.push(num);
}
for(int i = 0; i < 4; i++)
{
cin >> num;
vector2.push(num);
}
vector3 = vector1 + vector2;
for(int i = 0; i < 4; i++)
cout << vector3.pop() << endl;
}
You create dynamic array with zero size in default constructor.
But in push method you try to set value to it if it's length is zero.
In C++ standard it says:
The effect of dereferencing a pointer returned as a request for zero
size is undefined.
You can only delete it. Fix your push method
For a C++ class I am taking, I am creating a Vector Library. We are not allowed to use the built in vector library, of course, and I have decided to use arrays in my 'myvector' class.
I am currently trying to test my code and I am not sure how to create an object of class myvector.
The error I get is Incomplete type is not allowed.
main.cpp:
#include "my_vectorHeader.h"
using namespace std;
int main(){
myvector<int> vector = new myvector<int>(3);
}
my_vectorLib.cpp:
#include "my_vectorHeader.h"
#include iostream
#include exception
using namespace std;
template<typename T> class myvector {
private:
int vector_size, //holds current size
vector_capacity; //holds current capacity
public:
//constructors
myvector<T>(int length){
T vector[length];
vector_size = length;
vector_capacity = length;
}
myvector<T>(const T& doppelganger){
T vector = doppelganger;
while(vector[vector_size] != NULL)
vector_size++;
}
myvector<T>(const T& dat_arr, int arr_size){
vector_size = arr_size;
vector_capacity = arr_size;
for(int i = 0; i < arr_size; i++)
vector[i] = dat_arr[i];
}
~myvector(){ //destructor
delete [] vector;
delete myvector;
}
myvector& myvector::operator[](int index){ //override []
try{
throw vector[index];
} catch(exception e){
cout << e.what() << endl;
}
return vector[index];
}
T at(int index){
return vector[index];
}
int size(){
return vector_size;
}
int capacity(){
return vector_capacity;
}
bool empty(){
if(size() > 0)
return false;
else
return true;
}
void resize(int new_size){
T vector_copy[new_size];
for(int i = 0; i < new_size; i++){
if(i >= vector_size)
vector_copy[i] = NULL;
else
vector_copy[i] = vector[i];
if(new_size > capacity)
capacity = new_size;
}
vector_size = new_size;
delete [] vector;
T *vector;
vector = vector_copy;
for(int i = 0; i < vector_size; i++)
vector[i] = vector_copy[i];
delete [] vector_copy;
}
void reserve(int new_capacity){
if(new_capacity < vector_size){
cout << "Error. Newly provided vector capacity is smaller than the current vector size. The capacity is " << vector_capacity << " and has not been changed.";
} else {
vector_capacity = new_capacity;
}
}
T pop_back(){
T return_val = vector[size() - 1];
resize(size() - 1);
return return_val;
}
void push_back(T new_val){
resize(size() + 1);
vector[size() - 1] = new_val;
}
void assign(int position, T new_val){
vector[position] = new_val;
}
void clear(){
for(int i = 0; i < size(); i++)
vector[i] = NULL;
}
void erase(int position){
vector[position] = NULL;
do{
vector[position] = vector[position + 1];
}while(position != NULL);
resize(size() - 1);
}
void erase(int in, int between){
int i = in + 1, j = between;
while(i < between){
vector[i] = vector[j];
vector[j] = NULL;
i++, j++;
}
resize(between);
}
void insert(int index, T new_val){
for(int i = size + 1; i > index; i--)
vector[i] = vector[i - 1];
vector[index] = new_val;
}
};
Declaration and implementation of templates should be in the same file(or implementation should be included too). Also this
myvector<int> vector = new myvector<int>(3);
is incorrect(new returns pointer) and unnecessary. Just use
myvector<int> vector(3);
Put the class (all the code) found at my_vectorLib.cpp in your my_vectorLib.h As #soon pointed you, templates classes (unless specialized) need to be at the header file (the one you include at main.cpp which where the class is instantiated, which means the compiler generates the actual code when you use the template).