1

While creating a static library using c++11, it fails during linking I think.

I can create a static library and link to it using the information in How to create a static library with g++? with ordinary c++, but if I try to follow the steps using c++11 features, it fails during the linking.

test.cpp:

#include <iostream> #include <vector> #include "libtestlib.h" using namespace std; int main() { itest n1={{1,2,3,4}, {5,6,7,8}, {9,0,1,2}}; cout << "testing...\n"; test_print(n1); return 0; } 

libtestlib.h:

#ifndef testlib #define testlib #include <vector> using namespace std; typedef vector<vector<double>> dtest; typedef vector<vector<int>> itest; template <typename testtype> void test_print(testtype); #endif 

libtestlib.cpp:

#include <iostream> #include "libtestlib.h" using namespace std; template <typename testtype> void test_print(testtype &t) { int m=t.size(); int n=t[0].size(); for(int i=0; i<m; i++) { for(int j=0; j<n; j++) cout << t[i][j] << " "; cout << endl; } cout << endl; } 

this is the output I'm getting:

$ g++ -std=c++11 -c libtestlib.cpp $ ar rvs libtestlib.a libtestlib.o r - libtestlib.o $ g++ -std=c++11 test.cpp libtestlib.a /tmp/cccJ7SXZ.o:test.cpp:(.text+0x1af): undefined reference to `void test_print<std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > >(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >)' /tmp/cccJ7SXZ.o:test.cpp:(.text+0x1af): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `void test_print<std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > >(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >)' collect2: error: ld returned 1 exit status 
3
  • Your library is essentially empty since that is a templated function it won't have any instantiations. It should be in the libtestlib.h header or included into it. Once you do that you can statically compile it. Commented Apr 12, 2019 at 21:56
  • Thanks for your response @estabroo. Can you give an example of what you mean? Commented Apr 12, 2019 at 22:36
  • isocpp.org/wiki/faq/templates#templates-defn-vs-decl gives a good explanation. And for an example take your code above, move what's in libtestlib.cpp into libtestlib.h and compile it. g++ --std=c++11 -static -o test_it test.cpp Commented Apr 12, 2019 at 22:48

2 Answers 2

3

Since it seems you are supporting operations on a limited number of types, the classic "Just do it in a header" answer to this problem is not necessarily the best one.

You can get the best of both worlds by explicitely exporting a symbol for each implementation, but delegate the implementation to a template within the library:

libtestlib.h:

#ifndef testlib #define testlib #include <vector> using namespace std; typedef vector<vector<double>> dtest; typedef vector<vector<int>> itest; void test_print(dtest&); void test_print(itest&); 

libtestlib.cpp:

#include <iostream> #include "libtestlib.h" using namespace std; namespace { template <typename testtype> void test_print_impl(testtype &t) { int m=t.size(); int n=t[0].size(); for(int i=0; i<m; i++) { for(int j=0; j<n; j++) cout << t[i][j] << " "; cout << endl; } cout << endl; } } void test_print(dtest& val) { test_print_impl(val); } void test_print(itest& val) { test_print_impl(val); } 

Mind you, for a small function like this, it's probably not worth the effort, and just inlining the template code in the header is just fine. At what point does the complexity of a function and the scope of its dependencies warrant this is a bit of a judgement call.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks @Frank! Your solution works for me, but of course my real situation is not as simple/small as this example. :)
@Frank nice and actually gives you the option to build a static library, whereas in the header doesn't really lend itself to doing that.
1

Putting example requested from comment on the question here as code looked really ugly in a comment. Combined libtestlib.h and libtestlib.cpp

#ifndef testlib #define testlib #include <vector> #include <iostream> using namespace std; typedef vector<vector<double>> dtest; typedef vector<vector<int>> itest; template <typename testtype> void test_print(testtype &t) { int m=t.size(); int n=t[0].size(); for(int i=0; i<m; i++) { for(int j=0; j<n; j++) cout << t[i][j] << " "; cout << endl; } cout << endl; } #endif 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.