template array class is not working properly - c++

Template class :
#ifndef ARRAYC_H
#define ARRAYC_H
#include <iostream>
using namespace std;
template <class T>
class Array
{
private:
T* m_ptr;
int m_size;
public:
Array();
Array(int size);
~Array();
int size() const;
bool is_Empty() const;
T& operator[](int index);
};
#endif
and class declaration Header..
#ifndef ARRAY_H
#define ARRAY_H
#include "ArrayC.h"
using namespace std;
template <class T>
Array<T>::Array(int size) {
if(size!=0) {
T* m_ptr = new T[size]{};
m_size = size;
}
}
template <class T>
Array<T>::~Array() {
cout <<"Deleted" << endl;
delete [] m_ptr;
}
template <class T>
int Array<T>::size() const {
return m_size;
}
template <class T>
bool Array<T>::is_Empty() const {
return (m_size==0);
}
template <class T>
T& Array<T>::operator[](int index) {
if(index< m_size) {
return m_ptr[index];
}
else {
cout <<"Index Specifed is out of Range" << endl;
exit(0);
}
}
#endif
program
#include "Array.h"
#include <iostream>
using namespace std;
int main() {
Array<int> A(2);
A[0] = 1;
A[1] = 2;
cout << A[0] << endl;
cout << A[1] << endl;
}
it compiles and also outputs value but
then it stops and then makefile shows error.
g++ -g -std=c++17 -c -o Main.o Main.cpp
g++ -g -std=c++17 -o Execute Main.o
Execute
1
2
Deleted
Makefile:13: recipe for target 'run' failed
mingw32-make: *** [run] Error -1073741819
after deleted is printed it stops for some time and then shows error.
run target only has one recipe that is to execute the program Execute.exe.
Really sorry for this type of description
but its doesnt show any type of error.
CCX_FLAGS = g++ -g -std=c++17
CCX_OF = -o
CCX_CF = -c
.PHONY : all preExwork Obclean Exclean
all : preExwork run Obclean
preExwork :
$(CCX_FLAGS) $(CCX_CF) $(CCX_OF) Main.o Main.cpp
$(CCX_FLAGS) $(CCX_OF) Execute Main.o
run :
Execute
Obclean :
del /f Main.o
Exclean :
del /f Execute.exe

Related

C++ derived class constructor call base class constructor errors

I have a base class sprite:
sprite.hh
#include <iostream>
#include "vector.hh"
#ifndef SPRITE
#define SPRITE
class sprite
{
private:
vector pos;
//the width and height of the sprite
vector dimensions;
int imArrIndex;
public:
sprite();
sprite(vector p, vector d, int i);
void setPos(vector v);
vector getPos();
void setDimensions(vector v);
vector getDimensions();
void setImArrIndex(int i);
int getImArrIndex();
void movePos(vector v);
};
#endif
sprite.cc:
#include <iostream>
#include "sprite.hh"
#include "vector.hh"
using namespace std;
sprite::sprite()
{
cout << "sprite created\n";
}
sprite::sprite(vector p, vector d, int i)
{
pos = p;
dimensions = d;
imArrIndex = i;
}
void sprite::setPos(vector v)
{
pos = v;
}
vector sprite::getPos()
{
return pos;
}
void sprite::setDimensions(vector v)
{
dimensions = v;
}
vector sprite::getDimensions()
{
return dimensions;
}
void sprite::setImArrIndex(int i)
{
imArrIndex = i;
}
int sprite::getImArrIndex()
{
return imArrIndex;
}
void sprite::movePos(vector v)
{
pos.setX(pos.getX() + v.getX());
pos.setY(pos.getY() + v.getY());
}
and a derived class actor:
actor.hh:
#include <iostream>
#include "sprite.hh"
#include "vector.hh"
#ifndef ACTOR
#define ACTOR
class actor : public sprite
{
private:
public:
actor(vector p, vector d, int i) : sprite(p, d, i);
};
#endif
actor.cc:
#include <iostream>
#include "sprite.hh"
#include "actor.hh"
#include "vector.hh"
using namespace std;
actor::actor(vector p, vector d, int i) : sprite(p, d, i)
{
cout << "actor created\n";
}
Both classes use the vector class:
vector.hh:
#include <iostream>
#include <cmath>
#ifndef VECTOR
#define VECTOR
class vector
{
private:
int x;
int y;
public:
vector();
vector(int px, int py);
void setX(int px);
int getX();
void setY(int py);
int getY();
//get the pixel distance between this vector and a given vector
int getDistance(vector v);
};
#endif
vector.cc:
#include <iostream>
#include "vector.hh"
using namespace std;
vector::vector()
{
cout << "vector created\n";
}
vector::vector(int px, int py)
{
x = px;
y = py;
cout << "vector created\n";
}
void vector::setX(int px)
{
x = px;
}
int vector::getX()
{
return x;
}
void vector::setY(int py)
{
y = py;
}
int vector::getY()
{
return y;
}
//get the pixel distance between this vector and a given vector
int vector::getDistance(vector v)
{
return sqrt( pow(x - v.getX(), 2) + pow(y - v.getY(), 2) );
}
Right now I am just trying to get the constructor for the actor working in my main code with this section:
vector p(0,0);
vector d(0,0);
actor a(p, d, 1);
But I am getting this error when running my makefile:
g++ -c level.cc
In file included from level.cc:6:
actor.hh: In constructor ‘actor::actor(vector, vector, int)’:
actor.hh:15:53: error: expected ‘{’ at end of input
actor(vector p, vector d, int i) : sprite( p, d, i);
^
make: *** [makefile:11: level.o] Error 1
My makefile works just fine if I don't call the base constructor in the derived class so I'm sure its not an error in my makefile, but here is my makefile just in case:
FrogGame: frogmain.o game.o level.o sprite.o actor.o vector.o
g++ -std=c++0x -Wall -pedantic -o FrogGame frogmain.o game.o level.o sprite.o actor.o vector.o `sdl2-config --cflags --libs` -lSDL2_image
frogmain.o: frogmain.cc game.hh level.hh sprite.hh vector.hh
g++ -c frogmain.cc
game.o: game.cc level.hh sprite.hh actor.hh vector.hh
g++ -c game.cc
level.o: level.cc sprite.hh actor.hh vector.hh
g++ -c level.cc
actor.o: actor.cc vector.hh
g++ -c actor.cc
sprite.o: sprite.cc vector.hh
g++ -c sprite.cc
vector.o: vector.cc
g++ -c vector.cc
I'm assuming I have some syntax wrong in the constructor but can't seem to fix it, any suggestions?
In your header file, you have this line:
public:
actor(vector p, vector d, int i) : sprite(p, d, i); // Error!
I see what you're trying to do here, but this isn't legal C++ syntax. If you plan to declare the actor constructor but then define it in a .cpp file, which is what you're doing here, just write
actor(vector p, vector d, int i);
Then, in the .cpp file, as you've done, write
actor::actor(vector p, vector d, int i) : sprite(p, d, i)
{
cout << "actor created\n";
}
As you have it written right now, the C++ compiler sees the declaration of the actor constructor. When it then sees the initialization list (the : sprite(p, d, i) part), it thinks "oh, okay, you're defining the functions here." It's then mightily confused about why there's a semicolon instead of the actual body of the function, which is what the compiler error you're getting says.

Why am I getting the error 'undefined reference to `MinHeap<char>::insert(char, int)`' [duplicate]

This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 2 years ago.
I am currently trying to implement a min heap, however, I am running into an issue.
I am having difficulty determining why my code is not linking properly when I compile it. The files, commands, and error are as follows:
min_heap.h
#ifndef MIN_HEAP_H
#define MIN_HEAP_H
#include <vector>
#include <algorithm>
using namespace std;
template <typename T>
struct HeapNode {
HeapNode(const T data, const int key) : data(data), key(key) {}
bool operator<(const HeapNode<T>& rhs) {return this->key < rhs.key;}
bool operator<=(const HeapNode<T>& rhs) {return this->key <= rhs.key;}
T data;
int key;
};
template <typename T>
class MinHeap {
public:
MinHeap() {};
~MinHeap() {};
void insert(const T data, const int key);
T extract_min();
T peek() const;
int size() const;
private:
vector<HeapNode<T>> heap;
};
#endif
min_heap.cpp
#include <iostream>
#include "min_heap.h"
using namespace std;
template <typename T>
void MinHeap<T>::insert(const T data, const int key){
cout << "Insertion." << endl;
if(this->heap.size() == 0){
cout << "adding first node" << endl;
this->heap.push_back(new HeapNode<T>(data, key));
}else{
cout << "not first node." << endl;
this->heap.push_back(new HeapNode<T>(data, key));
int currentIndex = this->heap.size() - 1;
while(((currentIndex - 1) / 2) >= 0){
if(this->heap[(currentIndex - 1) / 2] > this->heap[currentIndex]){
swap(this->heap[currentIndex], this->heap[(currentIndex - 1) / 2]);
currentIndex = ((currentIndex - 1) / 2);
}else{
break;
}
}
}
}
template <typename T>
T MinHeap<T>::extract_min(){
T data;
data = NULL;
return data;
}
template<typename T>
T MinHeap<T>::peek() const{
T data;
if(this->heap.size() == 0){
cout << "size: 0" << endl;
data = NULL;
}else{
cout << "something in there" << endl;
data = this->heap[0];
}
return data;
}
template<typename T>
int MinHeap<T>::size() const {
return this->heap.size();
};
customMain.cpp
#include <iostream>
#include "min_heap.h"
using namespace std;
int main(){
MinHeap<char> heap = MinHeap<char>();
const char data = 'a';
const int key = 7;
heap.insert(data, key);
return 0;
}
I am compiling the files above with the following
g++ -c min_heap.cpp
g++ -c customMain.cpp
g++ min_heap.o customMain.o
The error:
customMain.o:customMain.cpp:(.text+0x41): undefined reference to `MinHeap<char>::insert(char, int)'
collect2.exe: error: ld returned 1 exit status
Any help would be greatly appreciated!
Two options.
1) Move the template implementations out of the cpp file, and put them in the header. The compiler, when compiling main.cpp, cannot see the code it needs to generate the specialisation for char, so you end up being left with an unresolved external. Moving the code to the header will solve the issue (almost all template code resides in header files)
2) You can export specialisations from the cpp file, but then the types are locked down in advance (i.e. you can only use the exported types), which kinda reduces the flexibility and whole point of using templates. That's why 99.99% of people choose option 1, 99.99% of the time.
// export specialisations for char, short, int, and float
template class MinHeap<char>;
template class MinHeap<short>;
template class MinHeap<int>;
template class MinHeap<float>;

what c++ syntax right for implementation of function of nested class with pass enum param as template argument?

Ok. Here code:
#include <iostream>
using namespace std;
template<typename T>
struct A {
enum Status {
one = 1
};
template< Status status >
struct C;
};
template<typename T>
template<typename A<T>::Status status >
struct A<T>::C {
void operator()() {
cout << "C: " << (int)status << endl;
};
// void operator()();
};
// template<typename T>
// template<typename A<T>::Status status >
// void A<T>::C<status>::operator()() {
// cout << "C: " << status << endl;
//}
int main()
{
A<int>::C<A<int>::one> c;
c();
return 0;
}
And it works with clang and g++ - compile and run.
But, if comment inline implementation A::C::operator()(), and uncomment commented declaration and out implementation:
#include <iostream>
using namespace std;
template<typename T>
struct A {
enum Status {
one = 1
};
template< Status status >
struct C;
};
template<typename T>
template<typename A<T>::Status status >
struct A<T>::C {
// void operator()() {
// cout << "C: " << (int)status << endl;
// };
void operator()();
};
template<typename T>
template<typename A<T>::Status status >
void A<T>::C<status>::operator()() {
cout << "C: " << status << endl;
}
int main()
{
A<int>::C<A<int>::one> c;
c();
return 0;
}
clang doesn't make this:
$ clang++ -std=c++11 main.cpp && ./a.out
main.cpp:28:23: error: nested name specifier 'A<T>::C<status>::' for declaration does not refer into a class, class template or class template partial specialization
void A<T>::C<status>::operator()() {
~~~~~~~~~~~~~~~~~^
1 error generated.
but g++ really works:
$ g++-4.8 -std=c++11 -O2 -Wall -pedantic -pthread main.cpp
C: 1
I tried compile code with Visual C++ 2010 on work PC but both samples failed. I can't verify it now (no windows PC) and I'm not sure - maybe I made other mistakes...
Where mistake in second sample and what syntax right for out implementation?
It looks to me that you are just forgot the template parameter in the implementation of struct C.
The following fixed code compiles file in Visual C++ 2010:
#include <iostream>
#include <string>
#include <sstream>
#include <iostream>
using namespace std;
template<typename T>
struct A {
enum Status {
one = 1
};
template< Status status >
struct C;
};
template<typename T>
template<typename A<T>::Status status >
struct A<T>::C<status> {
/*void operator()() {
cout << "C: " << (int)status << endl;
};*/
void operator()();
};
template<typename T>
template<typename A<T>::Status status >
void A<T>::C<status>::operator()() {
cout << "C: " << status << endl;
}
int main()
{
A<int>::C<A<int>::one> c;
c();
return 0;
}

How to get a whole row from database using SOCI?

... and save it into self-defined object type? I'm using PostgreSQL. When I have everything in one file, it works. But I wanted to split this into class-files like you always do when writing in cpp. When I divided my code into *.h and *.cpp files, I'm getting errors.
Here are my files:
test.h
class MyInt
{
public:
MyInt();
MyInt(int i);
void set(int i);
int get() const;
private:
int i_;
};
test.cpp
#include "test.h"
#include <soci.h>
#include <postgresql/soci-postgresql.h>
MyInt::MyInt()
{
}
MyInt::MyInt(int i)
{
this->i_ = i;
}
int MyInt::get() const
{
return this->i_;
}
void MyInt::set(int i)
{
this->i_ - i;
}
namespace soci
{
template <>
struct type_conversion<MyInt>
{
typedef int base_type;
static void from_base(int i, soci::indicator ind, MyInt & mi)
{
if (ind == soci::i_null)
{
throw soci_error("Null value not allowed for this type");
}
mi.set(i);
}
static void to_base(const MyInt & mi, int & i, soci::indicator & ind)
{
i = mi.get();
ind = soci::i_ok;
}
};
}
main.cpp
#include <iostream>
#include "test.h"
int main(int argc, char **argv)
{
MyInt i;
sql.open(soci::postgresql, "dbname=mydb user=postgres password=postgrespass");
sql << "SELECT count(*) FROM person;", soci::into(i);
std::cout << "We have " << i.get() << " persons in the database.\n";
sql.close();
return 0;
}
I compile it like this:
g++ main_test.cpp test.h test.cpp -o App -lsoci_core -lsoci_postgresql
-ldl -lpq -I /usr/local/include/soci -I /usr/include/postgresql
and got those errors:
In file included from /usr/local/include/soci/into-type.h:13:0,
from /usr/local/include/soci/blob-exchange.h:12,
from /usr/local/include/soci/soci.h:18,
from main_test.cpp:3:
/usr/local/include/soci/exchange-traits.h: In instantiation of â€soci::details::exchange_traits<MyInt>’:
/usr/local/include/soci/into.h:29:60: instantiated from â€soci::details::into_type_ptr soci::into(T&) [with T = MyInt, soci::details::into_type_ptr = soci::details::type_ptr<soci::details::into_type_base>]’
main_test.cpp:29:59: instantiated from here
/usr/local/include/soci/exchange-traits.h:35:5: error: incomplete type â€soci::details::exchange_traits<MyInt>’ used in nested name specifier
THE ABOVE PROBLEM IS SOLVED, TAKE A LOOK AT #JohnBandela ANSWER.
The code where you specialize type_conversion
template<>
struct type_conversion<MyInt>
Needs to be in test.h not test.cpp. The problem is if you have it in test.cpp like you do now, it is not visible in main.cpp where you are using SOCI

Why getting linker error with vector?

I have for homework to write my own abstract class Vector. I make some of the code, but when I try to compile it I have error. This is the code:
vector.hh:
#ifndef VECTOR__HH__
#define VECTOR__HH_
template<class T> class Vector {
int capacity_;
int size_;
T* buffer_;
void ensure_capacity(unsigned size);
public:
Vector(int capacity=10)
: capacity_(capacity), size_(0), buffer_(new T[capacity])
{ }
~Vector() {
delete []buffer_;
}
int size() const {
return size_;
}
bool empty() const {
return size_ == 0;
}
T& operator[](int n) {
return buffer_[n];
}
const T& operator[](int n) const {
return buffer_[n];
}
void clear() {
// TODO
}
int capacity() const {
return capacity_;
}
T& front() {
return buffer_[0];
}
const T& front() const {
return buffer_[0];
}
T& back() {
return buffer_[size_-1];
}
const T& back() const {
return buffer_[size_-1];
}
void push_back(const T& value);
};
#endif
vector.cc:
#include "vector.hh"
template<class T>
void Vector<T>::ensure_capacity(unsigned size) {
if(capacity_>size+1) {
return;
}
capacity_ = capacity_ ==0?1:capacity_;
while(capacity_<size+1) {
capacity_*=2;
}
T* old_buffer = buffer_;
buffer_ = new T[capacity_];
memcpy(buffer_, old_buffer, sizeof(T)*size_);
delete [] old_buffer;
}
template<class T>
void Vector<T>::push_back(const T& value) {
ensure_capacity(size()+1);
buffer_[size_] = value;
size_++;
buffer_[size_] = '/0';
}
main.cc:
#include "vector.hh"
#include <iostream>
using namespace std;
int main(int argc, char* argv[]) {
Vector<int> v(2);
v.push_back(10);
cout << v[0];
return 0;
}
And error is:
g++ -c -o main.o main.cc
g++ -Wall -g vector.o main.o -o hw02vector
main.o: In function 'main':
main.cc:(.text+0x37): undefined reference to 'Vector<int>::push_back(int const&)'
collect2: ld returned 1 exit status
make: * [hw02vector] Error 1
The linker error is coming because, for template classes the definition should always be visible. Either you can move all the content of vector.cc into vector.h. Or you can simply include vector.cc wherever you include vector.h.
side note:
Following lines in your .h file doesn't help:
#ifndef VECTOR__HH__
#define VECTOR__HH_
make both the macros similar such as, VECTOR__HH. This macros are used to avoid multiple inclusion of files.
In template programmming, the definition of the functions should be visible where the class template is defined. That is usually done by defining the functions inside the class itself.
So there are two ways you can solve your problem:
Move all the definitions from vector.cpp to vector.hh (which is in fact the usual solution). And delete Vector.cpp as its not needed.
Or, include the vector.cpp file at the end of vector.hh file, after the definition of Vector class template, like this:
#ifndef VECTOR__HH__
#define VECTOR__HH__ //<--- corrected this also!
template<class T>
class Vector {
//...
};
//...
#include "vector.cpp"
#endif VECTOR__HH__