создание статической библиотеки с использованием g ++ -std = c ++ 11 с использованием шаблонов - PullRequest
1 голос
/ 13 апреля 2019

Я думаю, что при создании статической библиотеки с использованием c ++ 11 она перестала работать во время компоновки.

Я могу создать статическую библиотеку и ссылаться на нее, используя информацию в Как создать статическую библиотеку с g ++? с обычным c ++, но если я попытаюсь выполнить шаги, используя функции c ++ 11 во время компоновки не работает.

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;
}

это вывод, который я получаю:

$ 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

Ответы [ 2 ]

3 голосов
/ 13 апреля 2019

Поскольку кажется, что вы поддерживаете операции с ограниченным числом типов, классический ответ "Просто сделайте это в заголовке" не обязательно является лучшим.

Вы можете получить лучшее изв обоих мирах путем явного экспорта символа для каждой реализации, но делегирования реализации в шаблон внутри библиотеки:

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);
}

Имейте в виду, что для такой небольшой функции это, вероятно, не стоит усилий, и просто вставить код шаблона в заголовок просто отлично.В какой момент сложность функции и область ее зависимостей гарантируют, что это своего рода суждение.

1 голос
/ 13 апреля 2019

Размещение примера запроса из комментария на вопрос здесь, так как код выглядел действительно ужасно в комментарии. Объединение libtestlib.h и 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
...