I have a class defined like this (trivial includes and preprocessor wrappers, etc. are omitted, but they are there):
In Matrix.h
namespace matrixmanip {
template<typename T>
class Matrix {
public:
void someFunc() const;
//...
};
template<typename T>
void Matrix<T>::someFunc() const {
//...
}
} // namespace matrixmanip
In bitTransform.h
#include "Matrix.h"
namespace matrixmanip {
Matrix<char> bitExpand(const Matrix<char> &mat);
} // namespace matrixmanip
In bitTransform.cpp
#include "bitTransform.h"
using namespace matrixmanip;
Matrix<char> bitExpand(const Matrix<char> &mat) {
mat.someFunc();
//...
}
In tester.cpp
#include "Matrix.h"
#include "bitTransform.h"
matrixmanip::Matrix<char> A ... // construct a character matrix, details of which are unimportant here
matrixmanip::Matrix<char> B = matrixmanip::bitExpand(A);
However, when I compile and link like this:
g++ -c tester.cpp
g++ -c bitTransform.cpp
g++ -Wall -O2 tester.o bitTransform.o -o tester
I get an undefined reference error, specifically
/tmp/ccateMEK.o: In function `main':
tester.cpp:(.text+0xbf9): undefined reference to `matrixmanip::bitExpand(matrixmanip::Matrix<char> const&)'
collect2: error: ld returned 1 exit status
Why am I getting this error? It seems to me that my namespace resolution is okay and my linkage is fine...
bitExpand defines a free function in global namespace, not in matrixmanip namespace. using directive does not move definitions into the namespace being used. You should put definition in proper namespace directly:
namespace matrixmanip
{
Matrix<char> bitExpand(const Matrix<char> &mat)
{
mat.someFunc();
//...
}
}
Related
Bellow code is successfully compiling at Visual studio & Solaris compiler. But getting the link error at g++ (SUSE Linux) 4.3.4. Please let me know how to fix this link error at linux?
Note: To make code simple and cleaner I have typed proxy code here.
//---------------- a1.h -----------
#ifndef __a1_h__
#define __a1_h__
#include <iostream>
#include <memory>
namespace ServiceManagement
{
template <typename T>
class ClassA1
{
public:
ClassA1() {}
typedef std::auto_ptr<T>(*addFunc)(int, int);
static void setAddFunc(addFunc f)
{
s_AddFunc = f;
}
private:
static addFunc s_AddFunc;
};
}
#endif
//---------------- b1.h -----------
#ifndef __b11_h__
#define __b11_h__
#include "a1.h"
typedef ServiceManagement::ClassA1<int> setPosType;
namespace ServiceManagement
{
class ClassB1
{
public:
ClassB1() {}
static void Register();
private:
std::auto_ptr<setPosType> m_ptrMsg;
};
}
#endif
//---------------- b1.cpp -----------
#include "b1.h"
#include <iostream>
using namespace std;
//setPosType::addFunc setPosType::s_AddFunc;
template <> setPosType::addFunc setPosType::s_AddFunc;
namespace AA
{
namespace v2
{
std::auto_ptr<int> message2_(int a, int b)
{
int c = a + b;
std::auto_ptr<int> p1(new int);
*p1.get() = c;
return p1;
}
}
}
namespace ServiceManagement
{
void ClassB1::Register()
{
setPosType::addFunc f1 = ::AA::v2::message2_;
setPosType::setAddFunc(f1);
}
}
int main()
{
int i = 0;
cin >> i;
return 0;
}
Link Error:
/usr/bin/c++ -pthread -g -w -W -Wall -Wno-long-long -g -ldl -lm -lnsl -m64 -o -pthread -std=gnu++0x -Bdynamic
.. build " CMakeFiles/templateTest.dir/b1.cpp.o -o ../../../../../..//templateTest -rdynamic
CMakeFiles/templateTest.dir/b1.cpp.o: In function **ServiceManagement::ClassA1<int>::setAddFunc(std::auto_ptr<int> (*)(int, int))'**:
/templateTest/**a1.h:18: undefined reference toServiceManagement::ClassA1::s_AddFunc'
collect2: ld returned 1 exit status**
Note 2:
already static variable is defined at b1.cpp like below,
template <> setPosType::addFunc setPosType::s_AddFunc;
1.) It works once you initialize the member variable:
template <> setPosType::addFunc setPosType::s_AddFunc = 0;
Obviously, without the initializer, this line is a declaration rather than a definition, but, honestly, I do not see why.
2.) Clang tells me that defining the static member outside its namespace is a C++11 extension. Better use
namespace ServiceManagement {
template <> setPosType::addFunc setPosType::s_AddFunc = 0;
}
I get this /tmp/ccnL7Yz1.o: In function 'main':
main.cpp:(.text+0x70): undefined reference to 'dng::genDungeon()'
main.cpp:(.text+0xf0): undefined reference to 'dng::clrDungeon(char**)'
collect2: error: ld returned 1 exit status error when I'm trying to compile my program. It worked great before I added namespace functions. I'm compiling it like this: g++ -std=c++11 main.cpp Dungeon.cpp
Dungeon.h
namespace dng {
char** genDungeon();
void clrDungeon(char**);
class Dungeon {
//Methods and variables
}
}
Dungeon.cpp
#include "Dungeon.h"
using namespace dng;
char** genDungeon()
{
//Stuff
}
void clrDungeon(char** dungeon)
{
//Another Stuff
}
/*Implementation of class methods
void Dungeon::genStart(){} -> like this */
main.cpp
#include "Dungeon.h"
int main ()
{
//Stuff
auto dungeon = dng::genDungeon();
//Stuff
dng::clrDungeon(dungeon);
return 0;
}
I also tried to make .o files by myself g++ -std=c++11 -c main.cpp g++ -std=c++11 -c Dungeon.cpp and then link them, but got the same error. What can be the problem?
Enclose the function definitions in the namespace dng where they are declared.
#include "Dungeon.h"
namespace dng
{
char** genDungeon()
{
//Stuff
}
void clrDungeon(char** dungeon)
{
//Another Stuff
}
//...
}
Or use qualified names.
include "Dungeon.h"
using namespace dng;
//...
char** dng::genDungeon()
{
//Stuff
}
void dng::clrDungeon(char** dungeon)
{
//Another Stuff
}
Otherwise, the functions are defined in the global namespace, and as a result, you declared four functions: two in the namespace dng and another two in the global namespace.
I'm having one of those "undefined reference to " errors when compiling a c++ program. I know this is common pitfall, but so far was unable to figure out what I'm doing wrong.
Here's the relevant code. Ex1Two_Sum.h:
#ifndef EX1TWO_SUM_H
#define EX1TWO_SUM_H
#include <vector>
using namespace std;
namespace ddc {
class Ex1Two_Sum
{
public:
void f();
protected:
private:
};
}
#endif
Ex1Two_Sum.cpp:
#include <vector>
#include <cstddef>
#include <iostream>
using namespace std;
namespace ddc {
class Ex1Two_Sum {
public:
void f(){
cout << "works" << endl;
}
};
}
And finally, main.cpp:
#include <iostream>
#include "Ex1Two_Sum.h"
using namespace std;
using namespace ddc;
int main()
{
Ex1Two_Sum ex1;
ex1.f();
return 0;
}
I compile as follows:
g++ -std=c++11 -c Ex1Two_Sum.cpp
g++ -std=c++11 -c main.cpp
g++ Ex1Two_Sum.o main.o
yielding the following message:
main.o: In function `main':
main.cpp:(.text+0x2c): undefined reference to `ddc::Ex1Two_Sum::f()'
collect2: error: ld returned 1 exit status
Your source file redefines the whole class, with an inline function definition, when it just needs to provide a non-inline function definition.
#include "Ex1Two_Sum.h"
void ddc::Ex1Two_Sum::f() {
std::cout << "should work\n";
}
Also, please don't put using namespace std; in a header. Not everyone wants the global namespace polluted in potentially surprising ways.
First, which line of the command throws that error?
Second, I think you forgot to include the Ex1Two_Sum.h in the Ex1Two_Sum.cpp
Third you need to change class ....... in Ex1Two_Sum.cpp to:
void Ex1Two_Sum::f(){...}
I have the following three files in the same directory:
citysim.cpp
#include "utils.h"
using namespace std;
int main()
{
City *c;
c = new City();
Graph<City *> g;
g.addVertex(c);
}
utils.h
#include <iostream>
#include <map>
#include <vector>
using namespace std;
class City {
public:
City() {}
private:
string name;
};
template <typename Tkey>
class Graph {
public:
Graph() {}
void addVertex(Tkey);
private:
vector<Tkey> v;
vector< vector<int> > e;
map<Tkey, int> key_map;
};
utils.cpp
#include "utils.h"
template <typename Tkey>
void Graph<Tkey>::addVertex(Tkey vertex)
{
v.push_back(vertex);
}
And I am really perplexed as to why the following compilation sequence produces the result indicated:
test> g++ -c citysim.cpp
test> g++ -c utils.cpp
test> g++ -o citysim citysim.o utils.o
citysim.o: In function `main':
citysim.cpp:(.text+0x4a): undefined reference to `Graph<City*>::addVertex(City*)'
collect2: ld returned 1 exit status
Any ideas or insights are appreciated!
Define everything of your templated class in your header file, not in a cpp file. Instead of having your utils.cpp have everything like this in your header file:
template <typename Tkey>
class Graph {
public:
Graph() {}
void addVertex(Tkey vertex)
{
v.push_back(vertex);
}
private:
vector<Tkey> v;
vector< vector<int> > e;
map<Tkey, int> key_map;
};
Here is the related reading in the faq...
EDIT:
(But you can define it later on like you did it in your cpp in the header file as well...)
Template functions must be written entirely on the header, their definitions can't go on the cpp file.
Is the following approach correct? Well i get a compilation error.
a.hpp is
#include <iostream>
class a
{
public:
void classa_f();
};
a.cpp is
#include "a.hpp"
void a::classa_f()
{
std::cout<< "a::classa_f\n";
}
main.cpp
#include <iostream>
namespace myname {
#include "a.hpp"
}
int main ()
{
myname::a obj;
obj.classa_f();
return 0;
}
I get the following error
g++ main.cpp a.o
/tmp/ccOOf5s7.o: In function main':
main.cpp:(.text+0x11): undefined reference tomyname::a::classa_f()'
collect2: ld returned 1 exit status
Well my question is, is it possible to have just the includes under the namespace but not the actual implementation, because I can see that compiler is searching the namespace for he definition of the function.which is actually not there.
namespace myname {
#include "a.hpp"
}
Declares a class method myname::a::classa_f , which obviously doesn't exist in your program. It's not valid.
In the implementation, you must
namespace myname
{
void a::classa_f()
{
std::cout<< "a::classa_f\n";
}
}
and please remove #include <iostream> from the hpp file, it gets imported into the namespace too.