Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Specialization of a free standing template function

Reply
Thread Tools

Specialization of a free standing template function

 
 
Daniel
Guest
Posts: n/a
 
      07-06-2013
Using Visual Studio v. 10

In test.hpp:

#ifndef TEST_HPP
#define TEST_HPP

#include <ostream>

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

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

In test.cpp:

#include "test.hpp"

namespace ns
{
template <>
void serialize(std:stream& 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
 
Reply With Quote
 
 
 
 
Geoff
Guest
Posts: n/a
 
      07-06-2013
On Fri, 5 Jul 2013 18:26:24 -0700 (PDT), Daniel
<(E-Mail Removed)> 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:stream& os, const T& A)
> {
> os << "null";
> }
>
> 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
>
>In test.cpp:
>
>#include "test.hpp"
>
>namespace ns
>{
> template <>
> void serialize(std:stream& 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.
 
Reply With Quote
 
 
 
 
Daniel
Guest
Posts: n/a
 
      07-06-2013
On Friday, July 5, 2013 9:44:37 PM UTC-4, Geoff wrote:
> On Fri, 5 Jul 2013 18:26:24 -0700 (PDT), Daniel
>
> <(E-Mail Removed)> 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:stream& os, const T& A)

>
> > {

>
> > os << "null";

>
> > }

>
> >

>
> > 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

>
> >

>
> >In test.cpp:

>
> >

>
> >#include "test.hpp"

>
> >

>
> >namespace ns

>
> >{

>
> > template <>

>
> > void serialize(std:stream& 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);
}



 
Reply With Quote
 
Ike Naar
Guest
Posts: n/a
 
      07-06-2013
On 2013-07-06, Daniel <(E-Mail Removed)> 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:stream& os, const T& A)
> {
> os << "null";
> }
>
> 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
>
> In test.cpp:
>
> #include "test.hpp"
>
> namespace ns
> {
> template <>
> void serialize(std:stream& 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.
 
Reply With Quote
 
Daniel
Guest
Posts: n/a
 
      07-06-2013
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
 
Reply With Quote
 
Gerhard Fiedler
Guest
Posts: n/a
 
      07-06-2013
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
>>
>> <(E-Mail Removed)> 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:stream& os, const T& A)

>>
>>> {

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

>>
>>> }

>>
>>>

>>
>>> 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

>>
>>>

>>
>>>In test.cpp:

>>
>>>

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

>>
>>>

>>
>>>namespace ns

>>
>>>{

>>
>>> template <>

>>
>>> void serialize(std:stream& 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:stream&,
double const&).

Gerhard
 
Reply With Quote
 
Geoff
Guest
Posts: n/a
 
      07-06-2013
On Fri, 5 Jul 2013 18:26:24 -0700 (PDT), Daniel
<(E-Mail Removed)> 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:stream& os, const T& A)
> {
> os << "null";
> }
>
> 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
>
>In test.cpp:
>
>#include "test.hpp"
>
>namespace ns
>{
> template <>
> void serialize(std:stream& 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.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Full specialization of a member function template of a class template Dave C++ 4 06-04-2010 12:15 PM
specialization of a template function in a template class?!?!? pookiebearbottom@yahoo.com C++ 2 08-07-2006 01:08 PM
template specialization overriding non-specialization? Joseph Turian C++ 2 04-16-2006 02:46 PM
Specialization of member function template in template class? Joseph Turian C++ 4 03-20-2006 10:07 AM
Member template function specialization in a template class Ruben Campos C++ 3 02-15-2005 10:40 AM



Advertisments