Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   Specialization of a free standing template function (http://www.velocityreviews.com/forums/t962469-specialization-of-a-free-standing-template-function.html)

Daniel 07-06-2013 01:26 AM

Specialization of a free standing template function
 
Using Visual Studio v. 10

In test.hpp:

#ifndef TEST_HPP
#define TEST_HPP

#include <ostream>

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

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

T A_;
};
}
#endif

In test.cpp:

#include "test.hpp"

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

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

ns::B<double> a(10.0); // *
}

This compiles and links, and the output is

10

(as expected.)

However, if I include a second cpp file in the build, and move line *
to a function in that file, I get a linker error

serialize ... already defined in test.obj

Am I doing something wrong?

Thanks,
Daniel

Geoff 07-06-2013 01:44 AM

Re: Specialization of a free standing template function
 
On Fri, 5 Jul 2013 18:26:24 -0700 (PDT), Daniel
<danielaparker@gmail.com> wrote:

>Using Visual Studio v. 10
>
>In test.hpp:
>
>#ifndef TEST_HPP
>#define TEST_HPP
>
>#include <ostream>
>
>namespace ns
>{
> template <class T>
> void serialize(std::ostream& os, const T& A)
> {
> os << "null";
> }
>
> template <class T>
> class A
> {
> public:
> A(const T& A)
> : A_(A)
> {
> }
> void serialize(std::ostream& os) const
> {
> ns::serialize(os,A_);
> }
>
> T A_;
> };
>}
>#endif
>
>In test.cpp:
>
>#include "test.hpp"
>
>namespace ns
>{
> template <>
> void serialize(std::ostream& os, const double& A)
> {
> os << A;
> }
>}
>
>int main()
>{
> ns::A<double> a(10.0);
> a.serialize(std::cout);
>
> ns::B<double> a(10.0); // *
>}
>
>This compiles and links, and the output is
>
>10
>
>(as expected.)
>
>However, if I include a second cpp file in the build, and move line *
>to a function in that file, I get a linker error
>
>serialize ... already defined in test.obj
>
>Am I doing something wrong?


Yes, you didn't post the code that's causing your problem.
>
>Thanks,
>Daniel


Show us the additional CPP file.

Daniel 07-06-2013 02:32 AM

Re: Specialization of a free standing template function
 
On Friday, July 5, 2013 9:44:37 PM UTC-4, Geoff wrote:
> On Fri, 5 Jul 2013 18:26:24 -0700 (PDT), Daniel
>
> <danielaparker@gmail.com> wrote:
>
>
>
> >Using Visual Studio v. 10

>
> >

>
> >In test.hpp:

>
> >

>
> >#ifndef TEST_HPP

>
> >#define TEST_HPP

>
> >

>
> >#include <ostream>

>
> >

>
> >namespace ns

>
> >{

>
> > template <class T>

>
> > void serialize(std::ostream& os, const T& A)

>
> > {

>
> > os << "null";

>
> > }

>
> >

>
> > template <class T>

>
> > class A

>
> > {

>
> > public:

>
> > A(const T& A)

>
> > : A_(A)

>
> > {

>
> > }

>
> > void serialize(std::ostream& os) const

>
> > {

>
> > ns::serialize(os,A_);

>
> > }

>
> >

>
> > T A_;

>
> > };

>
> >}

>
> >#endif

>
> >

>
> >In test.cpp:

>
> >

>
> >#include "test.hpp"

>
> >

>
> >namespace ns

>
> >{

>
> > template <>

>
> > void serialize(std::ostream& os, const double& A)

>
> > {

>
> > os << A;

>
> > }

>
> >}

>
> >

>
> >int main()

>
> >{

>
> > ns::A<double> a(10.0);

>
> > a.serialize(std::cout);

>
> >

>
> > ns::B<double> a(10.0); // *

>
> >}

>
> >

>
> >This compiles and links, and the output is

>
> >

>
> >10

>
> >

>
> >(as expected.)

>
> >

>
> >However, if I include a second cpp file in the build, and move line *

>
> >to a function in that file, I get a linker error

>
> >

>
> >serialize ... already defined in test.obj

>
> >

>
> >Am I doing something wrong?

>
>
>
> Yes, you didn't post the code that's causing your problem.
>
> >

>
> >Thanks,

>
> >Daniel

>
>
>
> Show us the additional CPP file.


Well, this will do, in test1.cpp

#include "test.hpp"

void f()
{
ns::A<double> a(10.0);
}




Ike Naar 07-06-2013 05:37 AM

Re: Specialization of a free standing template function
 
On 2013-07-06, Daniel <danielaparker@gmail.com> wrote:
> Using Visual Studio v. 10
>
> In test.hpp:
>
> #ifndef TEST_HPP
> #define TEST_HPP
>
> #include <ostream>
>
> namespace ns
> {
> template <class T>
> void serialize(std::ostream& os, const T& A)
> {
> os << "null";
> }
>
> template <class T>
> class A
> {
> public:
> A(const T& A)
> : A_(A)
> {
> }
> void serialize(std::ostream& os) const
> {
> ns::serialize(os,A_);
> }
>
> T A_;
> };
> }
> #endif
>
> In test.cpp:
>
> #include "test.hpp"
>
> namespace ns
> {
> template <>
> void serialize(std::ostream& os, const double& A)
> {
> os << A;
> }
> }
>
> int main()
> {
> ns::A<double> a(10.0);
> a.serialize(std::cout);
>
> ns::B<double> a(10.0); // *


This should not compile; B is undeclared.

Daniel 07-06-2013 09:59 AM

Re: Specialization of a free standing template function
 
On Saturday, July 6, 2013 1:37:20 AM UTC-4, Ike Naar wrote:
>
> > ns::B<double> a(10.0); // *

>
>
>
> This should not compile; B is undeclared.


Sorry, that should have been

ns::A<double> b(10.0); // *

Everything else copied exactly from (non-working) code :-)

Daniel

Gerhard Fiedler 07-06-2013 12:29 PM

Re: Specialization of a free standing template function
 
Daniel wrote:

> On Friday, July 5, 2013 9:44:37 PM UTC-4, Geoff wrote:
>> On Fri, 5 Jul 2013 18:26:24 -0700 (PDT), Daniel
>>
>> <danielaparker@gmail.com> wrote:
>>
>>>Using Visual Studio v. 10

>>
>>>

>>
>>>In test.hpp:

>>
>>>

>>
>>>#ifndef TEST_HPP

>>
>>>#define TEST_HPP

>>
>>>

>>
>>>#include <ostream>

>>
>>>

>>
>>>namespace ns

>>
>>>{

>>
>>> template <class T>

>>
>>> void serialize(std::ostream& os, const T& A)

>>
>>> {

>>
>>> os << "null";

>>
>>> }

>>
>>>

>>
>>> template <class T>

>>
>>> class A

>>
>>> {

>>
>>> public:

>>
>>> A(const T& A)

>>
>>> : A_(A)

>>
>>> {

>>
>>> }

>>
>>> void serialize(std::ostream& os) const

>>
>>> {

>>
>>> ns::serialize(os,A_);

>>
>>> }

>>
>>>

>>
>>> T A_;

>>
>>> };

>>
>>>}

>>
>>>#endif

>>
>>>

>>
>>>In test.cpp:

>>
>>>

>>
>>>#include "test.hpp"

>>
>>>

>>
>>>namespace ns

>>
>>>{

>>
>>> template <>

>>
>>> void serialize(std::ostream& os, const double& A)

>>
>>> {

>>
>>> os << A;

>>
>>> }

>>
>>>}

>>
>>>

>>
>>>int main()

>>
>>>{

>>
>>> ns::A<double> a(10.0);

>>
>>> a.serialize(std::cout);

>>
>>>

>>
>>> ns::B<double> a(10.0); // *

>>
>>>}

>>
>>>

>>
>>>This compiles and links, and the output is

>>
>>>

>>
>>>10

>>
>>>

>>
>>>(as expected.)

>>
>>>

>>
>>>However, if I include a second cpp file in the build, and move line *

>>
>>>to a function in that file, I get a linker error

>>
>>>

>>
>>>serialize ... already defined in test.obj

>>
>>>

>>
>>>Am I doing something wrong?

>>
>> Yes, you didn't post the code that's causing your problem.
>>
>>>

>>
>>>Thanks,

>>
>>>Daniel

>>
>> Show us the additional CPP file.

>
> Well, this will do, in test1.cpp
>
> #include "test.hpp"
>
> void f()
> {
> ns::A<double> a(10.0);
> }


(The double spacing looks odd.)

I think you created two definitions of the serialize function.

In test1.cpp, you instantiate the template as defined in test.hpp, with
T=double. But in test.cpp, you define a specialization for T=double.

Compiling each file works, because they don't know of each other, but
the linker wants each symbol to be defined once, and here you have two
definitions for the same function ns::serialize<double>(std::ostream&,
double const&).

Gerhard

Geoff 07-06-2013 04:34 PM

Re: Specialization of a free standing template function
 
On Fri, 5 Jul 2013 18:26:24 -0700 (PDT), Daniel
<danielaparker@gmail.com> wrote:

>Using Visual Studio v. 10
>
>In test.hpp:
>
>#ifndef TEST_HPP
>#define TEST_HPP
>
>#include <ostream>
>


I think you mean <iostream> here. It won't compile without it.

>namespace ns
>{
> template <class T>
> void serialize(std::ostream& os, const T& A)
> {
> os << "null";
> }
>
> template <class T>
> class A
> {
> public:
> A(const T& A)
> : A_(A)
> {
> }
> void serialize(std::ostream& os) const
> {
> ns::serialize(os,A_);
> }
>
> T A_;
> };
>}
>#endif
>
>In test.cpp:
>
>#include "test.hpp"
>
>namespace ns
>{
> template <>
> void serialize(std::ostream& os, const double& A)
> {
> os << A;
> }
>}
>
>int main()
>{
> ns::A<double> a(10.0);
> a.serialize(std::cout);
>
> ns::B<double> a(10.0); // *
>}


Won't compile as written. Changing it to:
ns::A<double> a(10.0); // *

yields error C2374: 'a' : redefinition; multiple initialization

Writing:
ns::A<double> b(10.0); // *

compiles and links and your test1.cpp present or not, doesn't affect
the link.

>
>This compiles and links, and the output is
>
>10
>
>(as expected.)
>
>However, if I include a second cpp file in the build, and move line *
>to a function in that file, I get a linker error


Move or copy?

>
>serialize ... already defined in test.obj
>
>Am I doing something wrong?
>


Incremental link getting messed up? Clean and rebuild the project.
I tested this in VS2010 and Apple LLVM 4.2 and it links clean.


All times are GMT. The time now is 11:11 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.