|
-
February 27th, 2003, 12:23 PM
#1
global template function problem
Hi there,
I am trying to provide a global function to be used in quite a few classes but I just keep getting linker errors (this is using gcc).
My header file looks like this:
//A simple streamcasting TEMPLATE function
#ifndef _STREAMCAST_H_
#define _STREAMCAST_H_
#include <strstream>
#include <iostream>
template <class Type>
std::string stream_cast( Type const& );
#endif
and my source file like this:
#include "stream_cast.h"
#include <strstream>
#include <iostream>
using namespace std;
template <class Type>
string stream_cast( Type const& from )
{
strstream stream;
string to;
stream << from;
stream >> to;
return to;
}
I seem to get linker errors if I try to call this function even though I am definitely including the header file. Examples of linker error:
This line (where i is an unsigned int):
plot_command+=", \'\' u 1:"+stream_cast(i+1);
produces this
ld: Undefined symbols:
std::basic_string<char, std::char_traits<char>, std::allocator<char> > stream_cast<unsigned>(unsigned const&)
AND (where example is a double)
string title;
title=title+stream_cast(example);
produces this
ld: Undefined symbols:
stream_cast(double const&)
Its weird because it works fine if you include it in one of the class source files and only call it from that source file.
Thanks
-
February 27th, 2003, 12:28 PM
#2
You need to inline all the template code in the header file.
Jeff
-
February 27th, 2003, 12:45 PM
#3
OK.
I have tried that but I still get the same results.
I have made my source file blank and changed my header file to:
#ifndef _STREAMCAST_H_
#define _STREAMCAST_H_
#include <strstream>
#include <iostream>
template <class Type>
inline std::string stream_cast( Type const& from)
{
std::strstream stream;
std::string to;
stream << from;
stream >> to;
return to;
}
#endif
But the same problems arise. Interestingly if in the first example i gave I change an unsigned int to an int it seems to work, but still fails with the double.
very confusing
-
February 27th, 2003, 01:01 PM
#4
This works on VC++ 6.0:
Code:
#include <strstream>
#include <iostream>
#include <string>
template <class Type>
inline std::string stream_cast( Type const& from)
{
std::strstream stream;
std::string to;
stream << from;
stream >> to;
return to;
}
int main()
{
double d = 2.5;
std::cout << stream_cast(d);
return 0;
}
Make sure you don't have the orginal source file in the project and make sure everyting relying on the header file is rebuilt.
Jeff
-
February 27th, 2003, 01:47 PM
#5
Slightly simpler version:
Code:
template <class Type>
inline std::string stream_cast( Type const& from)
{
std::strstream stream;
stream << from;
return stream.str();
}
Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
-- Sutter and Alexandrescu, C++ Coding Standards
Programs must be written for people to read, and only incidentally for machines to execute.
-- Harold Abelson and Gerald Jay Sussman
The cheapest, fastest and most reliable components of a computer system are those that aren't there.
-- Gordon Bell
-
February 27th, 2003, 02:05 PM
#6
Just a small note, if your compiler supports it you should
use stringstream instead. strstream is deprecated.
-
February 27th, 2003, 02:42 PM
#7
I may be wrong about this ... but I believe that strstream::str()
returns a char* that won't be delete'd unless the programmer
calls freeze before the strstream object goes out of scope.
It has some weird behavior like that ... and that's just one of the
many reasons that people recommend you use stringstream
-
February 27th, 2003, 02:56 PM
#8
According to Josuttis, strstream::str() calls the member function
freeze() implicitly. However, it does not automatically
append a string termination character ('\0') - you need
to do it explicitly (std::ends)
-
February 27th, 2003, 04:01 PM
#9
Yeah that's it :) On that same page [650] check out #1:
Beause ownership of the memory is transferred to the caller,
unless the stream was initialized with a buffer of fixed size, the
character sequence has to be released. However, there is no
guarantee how the memory was allocated, thus is is not always
safe to release it using delete[]. Your best bet is to return the
memory to the stream by calling the member function freeze()
with the argument false
This is what strstream does NOT do. Josuttis gives some
examples for strstream usage:
Code:
std::ostrstream buffer;
buffer << "float X: " << x << std::ends;
char* s = buffer.str();
foo(s);
buffer.freeze(false);
Without that buffer.freeze(false), there would be a memory leak.
That's all I was really implying in my last post. This only helps to
reinforce your and Graham's argument to not use strstream :)
--Paul
-
February 27th, 2003, 04:29 PM
#10
Actually, I think I was being slack and meant std::ostringstream. std::ostringstream::str() returns a std::string, of course. In my defence, I've been out of work for a while now, so my reference sources are a bit thin.....
Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
-- Sutter and Alexandrescu, C++ Coding Standards
Programs must be written for people to read, and only incidentally for machines to execute.
-- Harold Abelson and Gerald Jay Sussman
The cheapest, fastest and most reliable components of a computer system are those that aren't there.
-- Gordon Bell
-
February 27th, 2003, 05:21 PM
#11
I'm sorry. I wasn't trying to make light of your post or anything;
I was just telling the original poster about the disadvantages of
strstream. Anyway, it's all water under the bridge now 
--Paul
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|