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
Using GCC 4.3.2 (and also "IBM XL C/C++ for AIX, V11.1 (5724-X13)"), I get the results that I expect:
$ 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
That is, I've injected new functionality into the client by linking it with an object that provides a more-specialized function template than the one offered by the library.
However, if I use "CC: Sun C++ 5.12 SunOS_sparc Patch 148506-14 2013/09/24", then I get this error:
$ 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
My solution must work with all three of these compilers. Am I just getting lucky with some undefined behavior in GCC and AIX? Are there some options I could pass to the Sun compiler to get this to work? Does what I'm trying to do show that I'm not fully understanding these template concepts? Enlighten me, please!