Problem fixed. Thanks a lot!
I am having the following error in the code shown below:
Error is as follows:
$ g++ main.cpp Neighbor.cpp Graph.cpp
/tmp/ccclDcUN.o: In functionmain':
main.cpp:(.text+0xc1): undefined reference to
Graph::add(int, Neighbor&)'
main.cpp:(.text+0xd3): undefined reference to `Graph::add(int, Neighbor&)'
collect2: ld returned 1 exit status
what could be going wrong?
// FILENAME: Graph.cpp
#include "Neighbor.h"
#include "Graph.h"
template <typename NS>
void Graph<NS>::add(int id,NS& n){
if(id>=adj_list.size())
while(adj_list.size()<id+1)
adj_list.push_back(list<NS>());
adj_list[id].push_back(n);
}
template <typename NS>
void Graph<NS>::remove(int id,NS& n){
if(id<adj_list.size()){
adj_list[id].remove(n);
}
}
// FILENAME: Graph.h
#ifndef GRAPH_H
#define GRAPH_H
#include "utils.h"
#include <vector>
#include <list>
class Neighbor;
template <typename NS>
class Graph {
private:
std::vector<std::list<NS> > adj_list;
public:
void add(int,NS&);
void remove(int,NS&);
inline typename std::vector<std::list<NS> >::iterator begin() { return adj_list.begin(); }
inline typename std::vector<std::list<NS> >::iterator end() { return adj_list.end(); }
};
#endif
// FILENAME: Neighbor.cpp
#include "Neighbor.h"
#include <iostream>
Neighbor::Neighbor(int id,float e,float p):id(id),edge_cost(e),price(p){}
bool operator==(const Neighbor& n1,const Neighbor& n2) {
if(&n1==&n2) return true;
return false;
}
ostream& operator<<(ostream& ostr,const Neighbor& n1) {
ostr<<"["<<n1.id<<","<<n1.price<<","<<n1.edge_cost<<"]";
return ostr;
}
// FILENAME: Neighbor.h
#ifndef NEIGHBOR_H
#define NEIGHBOR_H
#include <iosfwd>
class Neighbor {
private:
int id;
float edge_cost;
float price;
public:
Neighbor(int,float,float p=0.0);
friend bool operator==(const Neighbor&,const Neighbor&);
friend std::ostream& operator<<(std::ostream&,const Neighbor&);
};
#endif
// FILENAME: utils.h
#ifndef UTILS_H
#define UTILS_H
#include <iostream>
#include <fstream>
#include <stack>
#include <queue>
#include <vector>
#include <list>
#include <string>
#include <algorithm>
namespace utility {
typedef std::pair<int,int> ii;
typedef std::vector<int> vi;
typedef std::vector<ii> vii;
typedef std::vector<vii> vvii;
typedef std::stack<int> si;
typedef std::queue<int> qi;
}
#define UTILITY_TR(c,i) for(typeof((c).begin()) i = (c).begin() ; i!=(c).end() ; ++i )
#define UTILITY_ALL(c) (c).begin(),(c).end()
#define UTILITY_CPRESENT(c,x) (find(all(c),x) != (c).end())
#endif
// FILENAME: main.cpp
#include "utils.h"
#include "Neighbor.h开发者_高级运维"
#include "Graph.h"
using namespace std;
int main() {
Graph<Neighbor> graph;
Neighbor n1(1,10);
Neighbor n2(0,10);
graph.add(0,n1);
graph.add(1,n2);
cout<<"Printing graph"<<endl;
cout<<"--------------"<<endl;
UTILITY_TR(graph,it) {
UTILITY_TR(*it,n) {
cout<<*n<<endl;
}
}
};
What I usually do is manually verify the symbol exists in the library:
objdump --syms foo.o
This will output a list of symbols contained in the .o file... (since it's a link error, you should have .o files... (make sure you pass -c to g++ to get it to stop after compilation))... Then you can just visually verify the object has the symbols you think it does...
You need to have the definition of Graph's functions (add and remove) in the .h file so that the linker can find it.
I try to think of templates like envelopes. It's nonsensical to send it (compile) before you put in a letter (defined type). Seeing as cpp files are what is compiled, it makes sense that there shouldn't be cpp files for templated types.
HTH!
精彩评论