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";
}
Ok, so this problem has been bugging me for a while. I'm creating a c++ program with the libpcap and libnet libraries. It will scan a given country for open ports by SYN'ing with libnet and checking for replies with libpcap. I have a main.cpp file that includes network.h which includes the source files necessary for generating the IPv4 ranges (regex.cpp) and for scanning them (libnet.cpp). Now, my network.h file contains the definition for struct range which is just two uint32_t's representing the starting address of the range and the end.
network.h:
#ifndef NETWORK_H
#define NETWORK_H
#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
#include <regex>
#include <fstream>
#include <libnet.h>
#include <pcap.h>
#include "src/regex.cpp"
#include "src/libnet.cpp"
#include "src/libpcap.cpp"
#define COLOR_GREEN "\x1b[32m"
#define COLOR_RED "\x1b[31m"
#define COLOR_RESET "\x1b[0m"
#define SNAP_LEN 1518
typedef struct range {
uint32_t begin;
uint32_t end;
} range;
#endif
And I use struct range as the return type for getRangeByCountry
#include "../network.h"
std::vector<struct range> getRangeByCountry(const char* country){
std::vector<struct range> ranges;
try {
std::ifstream f("csv/geoip.csv");
std::regex re("\"\\d+.\\d+.\\d+.\\d+\",\"\\d+.\\d+.\\d+.\\d+\",\"(\\d+)\",\"(\\d+)\",\"\\w$
while (1){
std::string line;
std::getline(f, line);
std::smatch m;
if(line == ""){break;}
std::regex_match(line, m, re);
if (m[3] == country){
struct range r;
r.begin = std::stoul(std::string(m[1]), NULL, 0);
r.end = std::stoul(std::string(m[2]), NULL, 0);
ranges.push_back(r);
}
}
} catch (...){return ranges;}
return std::move(ranges);
}
But when I compile I get this error:
src/regex.cpp: In function ‘std::vector<range> getRangeByCountry(const
char*)’:
src/regex.cpp:15:17: error: aggregate ‘range r’ has incomplete type and
cannot be defined
struct range r;
Why doesn't the compiler throw an error when I set declare a vector of struct range locally? Or when I set the same as the return type? When I define the struct in the same file as getRangebyCountry() it compiles without error. Is this a problem with my g++ parameters? Here they are just in case: g++ main.cpp -lpcap -lnet --std=c++11
Fixed the problem. #Walter and #IgorTandetnik were right. In network I included a definition for getRangeByCountry() and removed the .cpp includes like so:
#ifndef _NETWORK_H
#define _NETWORK_H
#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
#include <regex>
#include <fstream>
#include <libnet.h>
#include <pcap.h>
#define COLOR_GREEN "\x1b[32m"
#define COLOR_RED "\x1b[31m"
#define COLOR_RESET "\x1b[0m"
#define SNAP_LEN 1518
std::vector<struct range> getRangeByCountry(const char*);
typedef struct range {
uint32_t begin;
uint32_t end;
} range;
Then I compiled regex.cpp separately and included it in my compilation of main.cpp like so: g++ main.cpp src/regex.o
But I'm still really shakey on the concept. If I want to include other cpp source files, do I need to compile them separately then include their definition in a header file and their actual definition in a .o when I compile main.cpp?
I have segregated the code in two files as shown below. Here is the header file graph.h
//graph.h
#ifdef GRAPH_H
#define GRAPH_H
#include <vector>
#include <fstream>
#include "kernel_def.h"
using namespace std;
typedef vector<bool> Array;
typedef vector<Array> TwoDArray;
class baseGraph {
private:
int nodes; /*Number of nodes.*/
vector<feature_vector *> vec; /*vector of feature nector.*/
public:
baseGraph(int nodes);
/*set-get functions*/
int getNodes();
void setNodes(int nodes);
const feature_vector *getVec(int pos);
int setVec(int pos, feature_vector *fVec);
/*Input edges from file and set up in corresponding representation.*/
virtual void setGraph(ifstream &ipf) = 0;
/*Utility functions*/
virtual void printGraph() = 0;
virtual feature_vector *subgraph_d(int node, int depth) = 0; /*subgraph upto depth d.*/
};
Here is graph.cpp
//graph.cpp
#include <iostream>
#include "graph.h"
using namespace std;
baseGraph::baseGraph(int nodes) {
setNodes(nodes);
/*feature vetors will be assigned later.*/
vec.resize(nodes);
for(int i=0;i<nodes; ++i)
vec.at(i) = NULL;
}
While compiling I get error that src/graph.cpp:7:1: error: ‘baseGraph’ does not name a type. I do not understand why this is happening. Any help appreciated.
First line of the source.
#ifdef GRAPH_H
should be
#ifndef GRAPH_H
I really don't understand how to fix this redefinition error.
COMPILE+ERRORS
g++ main.cpp list.cpp line.cpp
In file included from list.cpp:5:0:
line.h:2:8: error: redefinition of âstruct Lineâ
line.h:2:8: error: previous definition of âstruct Lineâ
main.cpp
#include <iostream>
using namespace std;
#include "list.h"
int main() {
int no;
// List list;
cout << "List Processor\n==============" << endl;
cout << "Enter number of items : ";
cin >> no;
// list.set(no);
// list.display();
}
list.h
#include "line.h"
#define MAX_LINES 10
using namespace std;
struct List{
private:
struct Line line[MAX_LINES];
public:
void set(int no);
void display() const;
};
line.h
#define MAX_CHARS 10
struct Line {
private:
int num;
char numOfItem[MAX_CHARS + 1]; // the one is null byte
public:
bool set(int n, const char* str);
void display() const;
};
list.cpp
#include <iostream>
#include <cstring>
using namespace std;
#include "list.h"
#include "line.h"
void List::set(int no) {}
void List::display() const {}
line.cpp
#include <iostream>
#include <cstring>
using namespace std;
#include "line.h"
bool Line::set(int n, const char* str) {}
void Line::display() const {}
You need to put include guards in your headers.
#ifndef LIST_H_
#define LIST_H_
// List.h code
#endif
In list.cpp, you are including both "line.h" and "list.h". But "list.h" already includes "line.h" so "list.h" is actually included twice in your code. (the preprocessor is not smart enough to not include something it already has).
There are two solutions:
Do not include "list.h" directly in your list.cpp file, but it is a practice that does not scale: you have to remember what every of your header file includes and that will be too much very quickly.
use include guards, as explained by #juanchopanza
You are including "line.h" twice, and you don't have include guards in your header files.
If you add something like:
#ifndef LINE_H
#define LINE_H
... rest of header file goes here ...
#endif
to your header files, it will all work out fine.
I have a problem with the definitions of my classes, probably because of the inclusion order or something.the error msg i receive is
g++ -I/opt/PDmesa/Mesa-5.0.1/include -I/opt/PDmesa/GLUT-3.7/include -c test.cpp
In file included from prog.h:16,
from test.cpp:10:
repeat.h:21: error: ‘Prog’ does not name a type
repeat.h:27: error: ‘Prog’ has not been declared
repeat.h: In constructor ‘Repeat::Repeat(float)’:
repeat.h:34: error: ‘in’ was not declared in this scope
repeat.h:34: error: ‘pg’ was not declared in this scope
repeat.h: In member function ‘virtual void Repeat::Run()’:
repeat.h:44: error: ‘class Repeat’ has no member named ‘pg’
make: *** [test.o] Error 1
%
so the question what should I do so i can use both of my classes?
main.cpp
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cstdlib>
#include <sstream>
#include <iterator>
#include "prog.h"
#include "window.h"
using namespace std;
Prog Turtle;
void draw(void)
{
Turtle.Run();
}
int main ( int argc, char** argv ) // Create Main Function For Bringing It All Together
{
filebuf fb;
fb.open (argv[1],ios::in);
istream input(&fb);
input>>Turtle;
fb.close();
window w(argc,argv);
}
prog.h
#ifndef PROG_H
#define PROG_H
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cstdlib>
#include <sstream>
#include <iterator>
#include "forward.h"
#include "left.h"
#include "right.h"
#include "jump.h"
#include "repeat.h"
using namespace std;
class Prog
{
private:
public:
Prog();
~Prog();
void Run();
void clearbuff();
vector<node*> listing;
friend istream& operator>> (istream& in, Prog& pro);
};
Prog::Prog()
{
//Default constructor
}
Prog::~Prog()
{
//Default destructor
}
void Prog::Run()
{
size_t sz=this->listing.size();
for (size_t it=0;it<sz;it++)
{
node* ptr = this->listing.at(it);
ptr->Run();
}
}
void Prog::clearbuff()
{
size_t sz=this->listing.size();
for (size_t it=0;it<sz;it++)
{
node* ptr = this->listing.at(it);
delete ptr;
}
}
istream& operator>> (istream& in, Prog& pro)
{
string tmp, command;
double value;
vector<string> text;
while (in>>tmp)
{
for (size_t i=0;i!=tmp.size()+1;++i)
tmp[i]=toupper(tmp[i]);
text.push_back(tmp);
}
while (!text.empty())
{
command=text[0];
istringstream inpStream(text[1]);
float value = 0.0;
if ((inpStream >> value)&&!text.empty())
{
if (command=="REPEAT")
{
unsigned int x(1), y(0), i(1), pos (0);
text.erase (text.begin(), text.begin()+2);
vector<string> reptext;
if (text[0]=="[")
{
for (i=1;(x!=y)&&i<=text.size();i++)
{
if (text[i]=="[")
++x;
else if (text[i]=="]")
++y;
reptext.push_back(text[i]);
pos=i;
}
reptext.erase(reptext.begin()+pos-1,reptext.end());
ofstream tempfile ("output.txt");
for(i=0; i<reptext.size(); i++)
tempfile << reptext[i] << endl;
tempfile.close();
filebuf rfb;
rfb.open ("output.txt",ios::in);
istream rin(&rfb);
pro.listing.push_back(new Repeat(value));
Prog ptm;
rin>>ptm;
rfb.close();
text.erase (text.end());
text.erase (text.begin(), text.begin()+3);
}
else
cout << "not a bracket found after repeat command --problemo";
}
else if (command=="FORWARD")
{
pro.listing.push_back(new Forward(value));
text.erase (text.begin(), text.begin()+2);
}
else if (command=="LEFT")
{
pro.listing.push_back(new Left(value));
text.erase (text.begin(), text.begin()+2);
}
else if (command=="RIGHT")
{
pro.listing.push_back(new Right(value));
text.erase (text.begin(), text.begin()+2);
}
else if (command=="JUMP")
{
pro.listing.push_back(new Jump(value));
text.erase (text.begin(), text.begin()+2);
}
else
cout << "Unknown command found in the input file!";
// text.erase(text.begin());
}
else
{
cout << " Value after command was not numeric or end of input file was reached!";
}
}
return in;
}
#endif // PROG_H
repeat.h
#ifndef REPEAT_H
#define REPEAT_H
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cstdlib>
#include <sstream>
#include <iterator>
#include "command.h"
#include "prog.h"
using namespace std;
class Repeat : public command
{
private:
Prog pg;
float repval;
public:
Repeat(float value);
~Repeat();
void Run();
friend istream& operator>> (istream& in, Prog& pro);
};
Repeat::Repeat(float value) : command(value)
{
this->repval=value;
for (int i=0;i<value;++i)
in>>pg; //ctor
}
Repeat::~Repeat()
{
}
void Repeat::Run()
{
this->pg.Run();
}
#endif // REPEAT_H
hello I added separate .cpp for each header that needs one. now I receive the following error
% make -f makefile3
g++ -I/opt/PDmesa/Mesa-5.0.1/include -I/opt/PDmesa/GLUT-3.7/include -c test.cpp
g++ -c forward.cpp
g++ -c left.cpp
g++ -c right.cpp
g++ -c jump.cpp
g++ -c repeat.cpp
g++ -c prog.cpp
g++ test.o -L/opt/PDmesa/Mesa-5.0.1/lib -L/opt/PDmesa/GLUT-3.7/lib -L/usr/X11R6/lib -lglut -lGLU -lGL -lX11 -lXext -lXmu -lXi -lm -o test
test.o: In function `draw()':
test.cpp:(.text+0x2ad): undefined reference to `Prog::Run()'
test.o: In function `main':
test.cpp:(.text+0x33a): undefined reference to `operator>>(std::basic_istream<char, std::char_traits<char> >&, Prog&)'
test.o: In function `__static_initialization_and_destruction_0(int, int)':
test.cpp:(.text+0x443): undefined reference to `Prog::Prog()'
test.cpp:(.text+0x448): undefined reference to `Prog::~Prog()'
collect2: ld returned 1 exit status
make: *** [test] Error 1
test.cpp
#include <iostream>
#include <fstream>
#include <sstream>
#include "prog.h"
#include "window.h"
using namespace std;
Prog Turtle;
void draw(void)
{
Turtle.Run();
// Turtle.clearbuff();
}
int main ( int argc, char** argv ) // Create Main Function For Bringing It All Together
{
filebuf fb;
fb.open (argv[1],ios::in);
istream input(&fb);
input>>Turtle;
fb.close();
window w(argc,argv);
}
prog.cpp
#include "prog.h"
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
#include <iterator>
#include "forward.h"
#include "left.h"
#include "right.h"
#include "jump.h"
#include "repeat.h"
Prog::Prog()
{
}
Prog::~Prog()
{
}
void Prog::Run()
{
size_t sz=this->listing.size();
for (size_t it=0;it<sz;it++)
{
node* ptr = this->listing.at(it);
ptr->Run();
}
}
void Prog::clearbuff()
{
size_t sz=this->listing.size();
for (size_t it=0;it<sz;it++)
{
node* ptr = this->listing.at(it);
delete ptr;
}
}
istream& operator>> (istream& in, Prog& pro)
{
string tmp, command;
double value;
vector<string> text;
while (in>>tmp)
{
for (size_t i=0;i!=tmp.size()+1;++i)
tmp[i]=toupper(tmp[i]);
text.push_back(tmp);
}
while (!text.empty())
{
command=text[0];
istringstream inpStream(text[1]);
float value = 0.0;
if ((inpStream >> value)&&!text.empty())
{
if (command=="REPEAT")
{
unsigned int x(1), y(0), i(1), pos (0);
text.erase (text.begin(), text.begin()+2);
vector<string> reptext;
if (text[0]=="[")
{
for (i=1;(x!=y)&&i<=text.size();i++)
{
if (text[i]=="[")
++x;
else if (text[i]=="]")
++y;
reptext.push_back(text[i]);
pos=i;
}
reptext.erase(reptext.begin()+pos-1,reptext.end());
ofstream tempfile ("output.txt");
for(i=0; i<reptext.size(); i++)
tempfile << reptext[i] << endl;
tempfile.close();
filebuf rfb;
rfb.open ("output.txt",ios::in);
istream rin(&rfb);
//pro.listing.push_back(new Repeat(value,rin));
Prog ptm;
rin>>ptm;
rfb.close();
for (int rp=0;rp<value;rp++)
{
cout << rp << endl;
for (i=0;i<ptm.listing.size();i++)
pro.listing.push_back(ptm.listing.at(i));
}
text.erase (text.end());
text.erase (text.begin(), text.begin()+3);
}
else
cout << "not a bracket found after repeat command --problemo";
}
else if (command=="FORWARD")
{
pro.listing.push_back(new Forward(value));
text.erase (text.begin(), text.begin()+2);
}
else if (command=="LEFT")
{
pro.listing.push_back(new Left(value));
text.erase (text.begin(), text.begin()+2);
}
else if (command=="RIGHT")
{
pro.listing.push_back(new Right(value));
text.erase (text.begin(), text.begin()+2);
}
else if (command=="JUMP")
{
pro.listing.push_back(new Jump(value));
text.erase (text.begin(), text.begin()+2);
}
else
cout << "Unknown command found in the input file!";
// text.erase(text.begin());
}
else
{
cout << " Value after command was not numeric or end of input file was reached!";
}
}
return in;
}
prog.h
#ifndef PROG_H
#define PROG_H
#include <iostream>
#include <fstream>
#include <vector>
#include "node.h"
using namespace std;
class Repeat;
class Prog
{
private:
public:
Prog();
~Prog();
void Run();
void clearbuff();
friend istream& operator>> (istream& in, Prog& pro);
vector<node*> listing;
};
#endif // PROG_H
repeat.cpp
#include "repeat.h"
using namespace std;
Repeat::Repeat(float value, istream in) : command(value)
{
this->repval=value;
for (int i=0;i<value;++i)
in>>pg; //ctor
}
Repeat::~Repeat()
{
}
void Repeat::Run()
{
this-> pg.Run();
}
repeat.h
#ifndef REPEAT_H
#define REPEAT_H
#include <iostream>
#include <fstream>
#include "command.h"
#include "prog.h"
using namespace std;
class Prog;
class Repeat : public command
{
private:
Prog pg;
float repval;
public:
Repeat(float value, istream in);
~Repeat();
void Run();
friend istream& operator>> (istream& in, Prog& pro);
};
#endif // REPEAT_H
if I remove #include "prog.h" and all references to Prog from test it compiles correctly but it doesnt actually work. also what I actually want to do is uncomment pro.listing.push_back(new Repeat(value,rin)); from prog.cpp and remove the next 10 lines.this line was the problem with the previous design. I supsect that Im doing again something wrong with the whole header thing
The problem here is that you have circular references.
You can think of a #include statement as simply cutting and pasting the contents of that file into the file where the directive is placed. There are several things you can do.
#1 - Put your implementation in a '.cpp' file
Your 'Prog' class definition does not mention Repeat. If you had a 'prog.cpp' file with the actual method definitions in it, you could #include "repeat.h" there and you wouldn't have any problems.
Other tricks include forward declarations, using pointers in your class defenition where a circular reference needs to take place, etc.
You are implementing the member functions for your classes in the header files. Don't do that. That is what the .cpp files are for.
You have a circular include. prog.h attempts to #include "repeat.h", and repeat.h attempts to #include "prog.h". One of these will get processed before the other, and then the header guards will prevent the other one from being processed. The net effect is that you don't end up #include ing everything you expected to, and then you have missing declarations.
This is easy to fix once we fix the first problem, because then we will no longer need to know about Repeat in the Prog header, and can just remove that #include statement. In the .cpp file, we include both headers, and there is no problem.
I would also like to refer you to http://www.gamedev.net/reference/articles/article1798.asp which explains all the common issues with header vs. implementation files in detail.
In prog.h you include repeat.h at the top of the file.
The body repeat.h doesn't see any of the Prog.h definitions.
Try having main.cpp include repeat.h directly
Remove #include "repeat.h" from prog.h
I can add that if both classes' declaration referenced each other so moving the implementations to *.cpp files wouldn't really help (although it still would be necessary), then you should have used forward declarations instead of includes, like this:
// in repeat.h
class Prog;
...
friend istream& operator>> (istream& in, Prog& pro);
// in prog.h
class Repeat;
...
void someMethodThatUsesRepeat(Repeat *rep);
Note that even if you don't have two classes referencing each other, using forward declarations may still be useful to speed up compilation since the compiler won't have to compile both headers each time when repeat.h is included.