Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Help with template friend and ostream, I think I am close

Reply
Thread Tools

Help with template friend and ostream, I think I am close

 
 
truce
Guest
Posts: n/a
 
      01-13-2006
I searched but couldn't find anything _quite_ like this. I have some
code I inherited that needs some work. Basically I have a template
that is instantiated in the c++ code and so only the headers are
distributed. That works great, the only problem is that I cant get
the friend ostream inserter operator to work correctly. Basically
it never is instantiated so it never shows up in the library. Here is
a (close to) minimum example demonstrating the problem. I want
to be able to do this without having all the code in the header since
I know what instances I will need. Thanks in advance -- I believe
I am close on this, but just can't quite get it.

// Foo.hh
using namespace::std;
#include <iostream>

template<int> class Foo;
template<int mp>
std:stream & operator<< (std:stream&, const Foo<mp> &);

template<int mp>
class Foo {
public:
char x[mp];
Foo();
friend std:stream & operator<< <>(std:stream&,const Foo<mp> &);
};

// end of Foo.hh

// Foo.cc

#include "Foo.hh"

template<int mp>
Foo<mp>::Foo()
{
int i;
for (i=0;i<mp;i++);
x[i] = i;
}

template<int mp>
std:stream & operator<< (std:stream&, const Foo<mp> &)
{
cout << "Nothing" << endl;
}

template class Foo<2>;

// end of Foo.cc


If I try to link this code when trying to use cout with an instance of
Foo<2>:

/tmp/test/Main.cc:8: undefined reference to `std::basic_ostream<char,
std::char_traits<char> >& operator<< <(int)2>(std::basic_ostream<char,
std::char_traits<char> >&, Foo<(int)2> const&)'

And to confirm an nm on the object file Foo.o gives me:

nm --demangle Foo.o
00000054 t global constructors keyed to _ZN3FooILi2EEC1EvFoo.ccAPePOb
00000000 t __static_initialization_and_destruction_0(int, int)
00000000 W Foo<2>::Foo()
00000000 W Foo<2>::Foo()
U std::ios_base::Init::Init()
U std::ios_base::Init::~Init()
00000000 b std::__ioinit
U __cxa_atexit
U __dso_handle
U __gxx_personality_v0
00000040 t __tcf_0



 
Reply With Quote
 
 
 
 
Earl Purple
Guest
Posts: n/a
 
      01-13-2006
The friend part is done correctly, the error is in here:

truce wrote:
>. Basically I have a template
> that is instantiated in the c++ code and so only the headers are
> distributed.


Unless you and everyone you distribute to uses a compiler that can
"export" templates, you cannot do that.

And then you'd have to use the export keyword.

 
Reply With Quote
 
 
 
 
=?iso-8859-1?q?Stephan_Br=F6nnimann?=
Guest
Posts: n/a
 
      01-13-2006
truce wrote:
> I searched but couldn't find anything _quite_ like this. I have some
> code I inherited that needs some work. Basically I have a template
> that is instantiated in the c++ code and so only the headers are
> distributed. That works great, the only problem is that I cant get
> the friend ostream inserter operator to work correctly.


The friendship of the output operator is not related to your problem.

> Basically
> it never is instantiated so it never shows up in the library. Here is
> a (close to) minimum example demonstrating the problem. I want
> to be able to do this without having all the code in the header since
> I know what instances I will need. Thanks in advance -- I believe
> I am close on this, but just can't quite get it.

[snip]

If you are really sure you know all instantiations of Foo<>:
be sure to call all related functions in foo.cc.

Regards, Stephan

 
Reply With Quote
 
truce
Guest
Posts: n/a
 
      01-13-2006

"Stephan Brönnimann" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed) oups.com...
> truce wrote:
>
>> Basically
>> it never is instantiated so it never shows up in the library. Here is
>> a (close to) minimum example demonstrating the problem. I want
>> to be able to do this without having all the code in the header since
>> I know what instances I will need. Thanks in advance -- I believe
>> I am close on this, but just can't quite get it.

> [snip]
>
> If you are really sure you know all instantiations of Foo<>:
> be sure to call all related functions in foo.cc.


This is the part that I dont understand. I dont know how to force
the operator function. I do know how to force the template though.

In foo.cc instantiate the objects for Foo of any type that I will ever use.
This makes g++ generate all of the code in the template for any
instances of Foo<2>. When compiled with the -fno-implicit-templates
flag, the code is not needed in the header file. So I can write another
piece of code, say main.cc such as this and link successfully even though
at the time of compilation, it does not generate the code. It is already
in Foo.o.

#include "Foo.hh"
int main(void) {
Foo<2> xyz;
....
}

But clearly, this usage doesn't force the friend function to get
instantiated that is why it does not link successfully. That is what I am
trying to force. In the same way that template class Foo<2> forces the
compiler to include all the code for the class, I want to force the friend
function to be compiled as well.

I did not get the other posters mention of the export keyword. But I
distribute the library, headers, Makefile, and the cross compiler as a
toolkit so I do know what they are using.


 
Reply With Quote
 
=?iso-8859-1?q?Stephan_Br=F6nnimann?=
Guest
Posts: n/a
 
      01-13-2006

truce wrote:
>
> This is the part that I dont understand. I dont know how to force
> the operator function. I do know how to force the template though.
>
> In foo.cc instantiate the objects for Foo of any type that I will ever use.
> This makes g++ generate all of the code in the template for any
> instances of Foo<2>. When compiled with the -fno-implicit-templates
> flag, the code is not needed in the header file. So I can write another
> piece of code, say main.cc such as this and link successfully even though
> at the time of compilation, it does not generate the code. It is already
> in Foo.o.

[OT]
Really?
The option -fno-implicit-templates is specific to g++
as well as its effects (I don't read the man page your way).
Just for fun: compile foo.cc with g++-3.3 and g++4.0, compare the
output.

By this your problem gets compiler (and most probaly version) specific:
How do I explictly instantiate a function template?
[/OT]

> #include "Foo.hh"
> int main(void) {
> Foo<2> xyz;
> ....
> }
>
> But clearly, this usage doesn't force the friend function to get
> instantiated that is why it does not link successfully. That is what I am
> trying to force. In the same way that template class Foo<2> forces the
> compiler to include all the code for the class, I want to force the friend
> function to be compiled as well.
>
> I did not get the other posters mention of the export keyword. But I
> distribute the library, headers, Makefile, and the cross compiler as a
> toolkit so I do know what they are using.


Regards, Stephan

 
Reply With Quote
 
truce
Guest
Posts: n/a
 
      01-14-2006

"Stephan Brönnimann" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed) ups.com...
>
> [OT]
> Really?
> The option -fno-implicit-templates is specific to g++
> as well as its effects (I don't read the man page your way).
> Just for fun: compile foo.cc with g++-3.3 and g++4.0, compare the
> output.
>


Tried your test. g++ 4.0.2, 3.3.5, and 3.4.4 all did
the *exact* same thing and worked correctly.
All three allowed me to compile the implementation
file and link against my main object.

Further, I figured out how to do it .... for the benefit of
those who run across the same opportunity and want to
distribute headers + a library using templates.

// At the bottom of Foo.cc
// create the code for the template
template class Foo<2>;
// create the code for the operator
template ostream& operator << (ostream&, const Foo<2>&);


 
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
Declaring a template class with two template params a friend in anon-template class A L C++ 1 08-25-2010 07:25 AM
How to close a TCP socket? (TCPSocket#close doesn't close it) Iñaki Baz Castillo Ruby 7 01-12-2010 01:32 PM
How can I declare and define a friend template function in a template class? =?gb2312?B?wfXquw==?= C++ 10 08-01-2007 01:48 AM
Need help: Is Quick-Union-Find the right solution to this problem (Now I don't think so and I think that topological sorting should be the way to go...?) ? aredo3604gif@yahoo.com C Programming 1 04-13-2005 12:48 AM
Need help: Is Quick-Union-Find the right solution to this problem (Now I don't think so and I think that topological sorting should be the way to go...?) ? aredo3604gif@yahoo.com C Programming 0 04-12-2005 05:06 PM



Advertisments