Внедрение зависимостей через специализацию шаблона

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, чтобы заставить это работать? Показывает ли то, что я пытаюсь сделать, что я не полностью понимаю эти концепции шаблона? Просвети меня, пожалуйста!

1

Решение

Ваш test двоичный файл, который связывает libmock.o а также client.o вместе нарушает одно правило определения (в модуле перевода клиента он использует версию по умолчанию, а в модуле перевода libmock он использует специализированную версию), и поэтому оба поведения компоновщика в порядке.

Я буду продолжать думать об альтернативах, но сейчас единственное решение, которое я могу придумать, состоит в том, чтобы включить условно libmock.h в client.cpp в зависимости от того, выполняете ли вы пробную сборку или нет.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]