multiple definition problems when using template specialization

Z

Zhang Guangyu

Using compiler vs2008.

I have declared a template function in foo.h.
foo.h:
template<class T> T foo(T value);
and defined it in foo.imp.
foo.imp:
template<class T> T foo (T value) { return value; }

I used this tempalte function in two files A.cpp and B.cpp which are
in the same project.
A.cpp:
#include "foo.h"
#include "foo.imp"
void funA() { foo<int>(1); }
B.cpp:
#include "foo.h"
#include "foo.imp"
void funB() { foo<int>(1); }

I would expect there is a link error of mulitple definition since both
the units have defined foo<int>, but the compiler worked fine. Why?

Then I want to use explicit specialization for foo<int>, so I put a
specialized definition in the foo.imp.
foo.imp:
template<class T> T foo (T value) { return value; }
template<> int foo<int> (int value) { return value+1; }
Then the compiler gave a link error that foo<int> was redefined.
Is there a way to solve this problem?
 
Z

Zhang Guangyu

Please start by reading section 35 of the FAQ.

Implementation of *real* functions cannot be in multiple translation
units unless the function is declared 'inline'.  Implementations of
function *templates* aren't really code until the template is
instantiated, they *have* to be visible by the compiler in every
translation unit where they are used.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask- Hide quoted text -

- Show quoted text -

The problem is that there are instiantiation in both B.cpp and C.cpp
so compiler will generate code for foo<int> in both units, but how the
linker does not generate an error of foo<int> redefinition?
 
I

Isti

The problem is that there are instiantiation in both B.cpp and C.cpp
so compiler will generate code for foo<int> in both units, but how the
linker does not generate an error of foo<int> redefinition?

You are on the right track.
Without explicit template specializations foo<int> will be specialized
in both A.obj and B.obj, but the linker is prepared for that and if
the two specializations are the same, then it will silently wipe out
one of them, and everything works fine as you experienced.

But if you explicitly state in your .impl file something like this:
template<> int foo<int> (int value);

it means that you will manually specialize the int-case, and since it
is a fully specialized function it behaves like a normal function.
so, the compiler won't generate any code for foo<int>: you have to do
it, but in a .cpp file, and only once in the whole project (as I said:
like for a normal function).

So the solution is to declare the fully specialized foo<int>()
in .impl (so the compiler knows that it don't have to automatically
generate any code for it):

template<> int foo<int> (int value);

then manually write the code in one (and only one) .cpp file:

template<> int foo<int> (int value)
{
return value+1;
}

I hope that it was helpful:
Istvan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,736
Latest member
AdolphBig6

Latest Threads

Top