lib.h:
#include <iostream>
namespace lib {
template <class T>
void f(T t)
{
std::cout << "lib f " << t << std::endl;
}
}
client.cpp:
#include "lib.h"
// explicit instantiation
template
void lib::f(char);
int main()
{
lib::f('x');
}
libmock.h:
#include <iostream>
#include "lib.h"namespace lib {
template <>
void f(char c)
{
std::cout << "libmock f " << c << std::endl;
}
}
Makefile:
run: prod test
./prod
./test
prod: client.o
${CXX} -o $@ $^
test: client.o libmock.o
${CXX} -o $@ $^
clean:
-rm *.o prod test
Используя GCC 4.3.2 (а также «IBM XL C / C ++ для AIX, V11.1 (5724-X13)»), я получаю ожидаемые результаты:
$ make
g++ -c -o client.o client.cpp
g++ -o prod client.o
g++ -c -o libmock.o libmock.cpp
g++ -o test client.o libmock.o
./prod
lib f x
./test
libmock f x
То есть я ввел новую функциональность в клиент, связав его с объектом, который предоставляет более специализированный шаблон функции, чем тот, который предлагается библиотекой.
Однако, если я использую «CC: Sun C ++ 5.12 SunOS_sparc Patch 148506-14 2013/09/24», то я получаю эту ошибку:
$ CXX=CC make
CC -c -o client.o client.cpp
CC -o prod client.o
CC -c -o libmock.o libmock.cpp
CC -o test client.o libmock.o
ld: fatal: symbol 'void lib::f<char>(__type_0)' is multiply-defined:
(file client.o type=FUNC; file libmock.o type=FUNC);
Makefile:9: recipe for target 'test' failed
make: *** [test] Error 2
Мое решение должно работать со всеми тремя из этих компиляторов. Мне просто повезло с неопределенным поведением в GCC и AIX? Есть ли варианты, которые я мог бы передать компилятору Sun, чтобы заставить это работать? Показывает ли то, что я пытаюсь сделать, что я не полностью понимаю эти концепции шаблона? Просвети меня, пожалуйста!
Ваш test
двоичный файл, который связывает libmock.o
а также client.o
вместе нарушает одно правило определения (в модуле перевода клиента он использует версию по умолчанию, а в модуле перевода libmock он использует специализированную версию), и поэтому оба поведения компоновщика в порядке.
Я буду продолжать думать об альтернативах, но сейчас единственное решение, которое я могу придумать, состоит в том, чтобы включить условно libmock.h
в client.cpp
в зависимости от того, выполняете ли вы пробную сборку или нет.
Других решений пока нет …