The project files is as this:
source
parser
parser.cpp
parser.hpp
brain
brain.cpp
brain.hpp
I first ran these two commands (pwd source/brain/
):
g++ -c brain.cpp -o brain.o
ar rvs brain.a brain.o
I copied both brain.a
and brain.hpp
to source/parser/
. Then I ran this command (pwd source/parser
):
g++ parser.cpp brain.a -o parser
And I got this error:
/tmp/cceGRLZn.o: In function `main':
parser.cpp:(.text+0x1cc): undefined reference to `std::brain<long long>::brain()'
parser.cpp:(.text+0x205): undefined reference to `std::brain<long long>::init(int)'
parser.cpp:(.text+0x26b): undefined reference to `std::brain<long long>::work()'
parser.cpp:(.text+0x2a4): undefined reference to `std::brain<long long>::clear()'
parser.cpp:(.text+0x2ec): undefined reference to `std::brain<long long>::~brain()'
parser.cpp:(.text+0x322): undefined reference to `std::brain<long long>::~brain()'
/tmp/cceGRLZn.o: In function `int parser_extract_args<long long>(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, int, short&, std::brain<long long>&)':
parser.cpp:(.text._Z19parser_extract_argsIxEiRSsiRsRSt5brainIT_E[int parser_extract_args<long long>(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, int, short&, std::brain<long long>&)]+0x17b): undefined reference to `std::brain<long long>::push_back(long long)'
parser.cpp:(.text._Z19parser_extract_argsIxEiRSsiRsRSt5brainIT_E[int parser_extract_args<long long>(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, int, short&, std::brain<long long>&)]+0x37a): undefined reference to `std::brain<long long>::push_back(long long)'
collect2: ld returned 1 exit status
Source files:
brain.cpp [http://ideone.com/GNUxmH][1]
brain.hpp [http://ideone.com/M2IFAI][2]
parser.cpp [http://ideone.com/fJRzhD][3]
parser.hpp [http://ideone.com/mj6dST][4]
What should I do?
I bet you implemented the member functions of your class template brain
in the .cpp
file. You need to provide template definitions in the header file so that the compiler can generate the appropriate code when it sees a template instantiation. So move the contents of brain.cpp
up to brain.h
.
As an example, consider these three files:
test.h
template <typename T>
struct test
{
void foo(T);
};
test.cpp
#include "test.h"
template <typename T>
void test<T>::foo(T x)
{
// do something with x
}
main.cpp
#include "test.h"
int main()
{
test<int> t;
t.foo(5);
}
Each .cpp
is compiled separately and then linked together. Imagine you are the compiler, and you're trying to compile main.cpp
. You see that the code wants to use the test
template instantiated with T
as int
. So now you need to generate the appropriate code for test<int>::foo
, but to do that you need to have seen the function's definition. Unfortunately, you haven't seen it, so you can't compile this program.
Instead, the definition of foo
should be moved into the header file to result in this two file program:
test.h
template <typename T>
struct test
{
void foo(T);
};
// Alternatively, you can define this up in the class definition
void test<T>::foo(T x)
{
// do something with x
}
main.cpp
#include "test.h"
int main()
{
test<int> t;
t.foo(5);
}
Note that you should not be adding your own declarations to the std
namespace:
The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace
std
unless otherwise specified.