Template function specialization once again (test a little, post a little)

D

Daniel

Special thanks to everyone who attempted to responded to my
original post, particularly Geoff and Gerhard.

This time I've hopefully posted code that better illustrates
my question. Basically the question is, does the output from
VC 10 for examples 1 and 2 below conform to expected output?

The context is a C++ template library that supports a default
serialization method for custom types, but allows the
library user to override it with something more sensible.

Example 1
=========

test.h
------

#ifndef TEST_HPP
#define TEST_HPP

#include <iostream>

namespace ns
{
template <class T>
void serialize(std::eek:stream& os, const T& A)
{
os << "null" << std::endl;
}

template <class T>
class A
{
public:
A(const T& A)
: A_(A)
{
}
void serialize(std::eek:stream& os) const
{
ns::serialize(os,A_);
}

T A_;
};
}
#endif

test1.h
-------

#ifndef TEST1_HPP
#define TEST1_HPP

void f();

#endif

test.cpp
--------

#include "test.h"
#include "test1.h"

int main()
{
ns::A<double> a(10.0);
a.serialize(std::cout);
f();
}


test1.cpp
---------

#include "test.h"

void f()
{
ns::A<double> b(10.0);
b.serialize(std::cout);
}

Visual Studio 10 gives the linker error
test1.obj : error LNK2005: "void __cdecl ns::serialize etc etc

: fatal error LNK1169: one or more multiply defined symbols found

So, test.cpp and test1.cpp induce different instantiations of
the function serialize with the same arguments?

Example 2
=========

test.h
------

Same as above

test1.h
-------

#ifndef TEST1_HPP
#define TEST1_HPP

#include <iostream>

void f();

namespace ns
{
template <>
void serialize(std::eek:stream& os, const double& A)
{
os << A << std::endl;
}
}

#endif

test.cpp
--------

Same as above

test1.cpp
---------

#include "test.h"
#include "test1.h"

void f()
{
ns::A<double> b(10.0);
b.serialize(std::cout);
}

Visual Studio 10 still gives the linker error

test1.obj : error LNK2005: "void __cdecl ns::serialize<double> etc.
LNK1169: one or more multiply defined symbols found

Even with template <>, the linker thinks there are multiple
definitions of serialize per header inclusion?

Example 3
=========

As above, except

test1.h
-------

#ifndef TEST1_HPP
#define TEST1_HPP

#include <iostream>

namespace ns
{
template <> inline
void serialize(std::eek:stream& os, const double& A)
{
os << A << std::endl;
}
}

#endif

--------------------------------

This time with inline in the template definition
Visual Studio 10 links and gives the correct result.
But should inline be necessary?

Example 4
=========

As above, except

test1.h
-------

#ifndef TEST1_HPP
#define TEST1_HPP

#include <iostream>

namespace ns
{
template <>
void serialize(std::eek:stream& os, const double& A);
}
#endif

test1.cpp
---------

#include "test.h"
#include "test1.h"

void f()
{
ns::A<double> b(10.0);
b.serialize(std::cout);
}

namespace ns
{
template<>
void serialize(std::eek:stream& os, const double& A)
{
os << A << std::endl;
}
}
 
B

Bart van Ingen Schenau

Special thanks to everyone who attempted to responded to my original
post, particularly Geoff and Gerhard.

This time I've hopefully posted code that better illustrates my
question. Basically the question is, does the output from VC 10 for
examples 1 and 2 below conform to expected output?

For example 1, no, for example 2, yes.
The context is a C++ template library that supports a default
serialization method for custom types, but allows the library user to
override it with something more sensible.

Example 1
=========

test.h
------

#ifndef TEST_HPP
#define TEST_HPP

#include <iostream>

namespace ns
{
template <class T>
void serialize(std::eek:stream& os, const T& A) {
os << "null" << std::endl;
}

template <class T>
class A
{
public:
A(const T& A)
: A_(A)
{
}
void serialize(std::eek:stream& os) const {
ns::serialize(os,A_);
}

T A_;
};
}
#endif

test1.h
-------

#ifndef TEST1_HPP
#define TEST1_HPP

void f();

#endif

test.cpp
--------

#include "test.h"
#include "test1.h"

int main()
{
ns::A<double> a(10.0);
a.serialize(std::cout);
f();
}


test1.cpp
---------

#include "test.h"

void f()
{
ns::A<double> b(10.0);
b.serialize(std::cout);
}

Visual Studio 10 gives the linker error


: fatal error LNK1169: one or more multiply defined symbols found

So, test.cpp and test1.cpp induce different instantiations of the
function serialize with the same arguments?

Both source files provide an implicit instantiation of
ns::serialize<double>, but because they are both implicit instantiations
of the same function template, that should be handled silently by the
compiler.
As the situation outlined in the code above occurs with just about any
project that uses the standard library from more than one source file, I
am not convinced that the posted code actually equals what you tested.
Example 2
=========

test.h
------

Same as above

test1.h
-------

#ifndef TEST1_HPP
#define TEST1_HPP

#include <iostream>

void f();

namespace ns
{
template <>
void serialize(std::eek:stream& os, const double& A) {
os << A << std::endl;
}
}

#endif

test.cpp
--------

Same as above

test1.cpp
---------

#include "test.h"
#include "test1.h"

void f()
{
ns::A<double> b(10.0);
b.serialize(std::cout);
}

Visual Studio 10 still gives the linker error

test1.obj : error LNK2005: "void __cdecl ns::serialize<double> etc.
LNK1169: one or more multiply defined symbols found

Even with template <>, the linker thinks there are multiple definitions
of serialize per header inclusion?

The linker is right here, because a specialization for a function
template is *not* a template itself, but just a regular function.
This means that the same rules apply to a function template
specialization as to a non-template function and only one source file may
provide a function definition (body) unless the function is explicitly
declared as inline.

<snip examples 3 and 4>

Bart v Ingen Schenau
 

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

No members online now.

Forum statistics

Threads
473,930
Messages
2,570,072
Members
46,522
Latest member
Mad-Ram

Latest Threads

Top