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:stream& os, const T& A)
{
os << "null" << std::endl;
}
template <class T>
class A
{
public:
A(const T& A)
: A_(A)
{
}
void serialize(std: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?
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: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: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: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:stream& os, const double& A)
{
os << A << std::endl;
}
}
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:stream& os, const T& A)
{
os << "null" << std::endl;
}
template <class T>
class A
{
public:
A(const T& A)
: A_(A)
{
}
void serialize(std: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: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: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: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:stream& os, const double& A)
{
os << A << std::endl;
}
}