问题
What is the function of the following C++ template class? I'm after line by line annotations:
template<class T> string toString(const T& t, bool *ok = NULL) {
ostringstream stream;
stream << t;
if(ok != NULL) *ok = stream.fail() == false;
return stream.str();
}
Is it like Java's toString()
method?
回答1:
Basically, it will take any object which has an operator<< defined for output to a stream, and converts it to a string. Optionally, if you pass the address of a bool varaible, it will set that based on whether or not the conversion succeeeded.
The advantage of this function is that, once defined, as soon as you defined operator<< for a new class you write, you immedaitely also get a toString() method for it as well.
template<class T>
string toString(const T& t, bool *ok = NULL)
{
ostringstream stream; // line A
stream << t; // line B
if(ok != NULL)
*ok = (stream.fail() == false); // line C
return stream.str(); // Line D
}
- A - Declares an ostringstream - an output stream that writes into a string
- B - Write your object into that stream, using it's operator<<
- C - Set *ok boolean to success/failure
- D - Convert the stream into a standard string & return it.
回答2:
This templated function accepts a value of any type and a pointer to a bool
. It attempts to use a std::ostringstream
to convert the value to a std::string
using the formatting conversions supplied by output streams. If the bool
-pointer parameter is non-null, the function writes whether the stream operation succeeded to the value at that pointer.
Thus it's possible to write:
std::string s = toString(123);
But it's also possible to write:
bool succeeded;
std::string s = toString(something, &succeeded);
if (succeeded) { ... }
That is, the function allows you to check whether the conversion was successful.
回答3:
It's not a template class. It's a template function/method. And indeed it does try to put the argument "t" into the stream. The operation might not succeed if the output stream(ostringstream) does not support handling input of type "T"(the "<<" operator does not know how to handle objects of type T).
回答4:
This is actually just a template function not a class. It provides simplified semantics for converting to a string for any type that can work with an ostringstream
(all numeric types will work and additional custom conversions can be defined). The function puts the value into the stream and then returns the string representation of the stream.
回答5:
Yes and no. It works on any object for which the operator <<
has been defined with an ostream. That or any object for which ostringstream
has an overloaded method to handle.
Either the object in question that you pass into the function has the following defined:
ostream& operator <<(ostream &os, MyObj &obj);
or it falls into one the standard overloads. Here is a list of the overloaded functions found within `ostream' taken from here:
ostream& operator<< (bool& val );
ostream& operator<< (short& val );
ostream& operator<< (unsigned short& val );
ostream& operator<< (int& val );
ostream& operator<< (unsigned int& val );
ostream& operator<< (long& val );
ostream& operator<< (unsigned long& val );
ostream& operator<< (float& val );
ostream& operator<< (double& val );
ostream& operator<< (long double& val );
ostream& operator<< (const void* val );
ostream& operator<< (streambuf* sb );
ostream& operator<< (ostream& ( *pf )(ostream&));
ostream& operator<< (ios& ( *pf )(ios&));
ostream& operator<< (ios_base& ( *pf )(ios_base&));
*** the following functions are not members but GLOBAL functions:
ostream& operator<< (ostream& out, char c );
ostream& operator<< (ostream& out, signed char c );
ostream& operator<< (ostream& out, unsigned char c );
ostream& operator<< (ostream& out, const char* s );
ostream& operator<< (ostream& out, const signed char* s );
ostream& operator<< (ostream& out, const unsigned char* s );
回答6:
First, this is not a class, it's just a function. Here's an annotated version:
// This function accepts two parameters, one of which is a constant reference
// to any arbitrary type (the arbitrary type is referred to as T), and the
// other is an optional pointer to boolean, which is NULL if left unspecified.
template<class T> string toString(const T& t, bool *ok = NULL) {
// This instantiates an output string stream, which is a class provided
// by the STL which works very much like std::cout except that the output
// is stored in a string instead of sent to standard output.
ostringstream stream;
// This inserts the passed-in variable t into the stream. This requires
// that a function operator<<(ostream&, const T&) exists for the
// particular type T that is the type of t. If it does not exist for some
// T that this function is called on, there will be a compile error. This
// operator overload is provided by default for built-in types and some STL
// types (such as std::string). The implementation of this function for any
// given type T is responsible for doing whatever needs to be done to
// represent the value of t as a character stream. This is exactly what
// happens when you write std::cout << t, except the result is sent to
// a string inside the stringstream instead of to the console.
stream << t;
// If the user passed in a pointer-to-boolean, then check if the previous
// line caused an error, and set the boolean to false if there was an error,
// or true otherwise. An error might occur if the value in t can't be
// represented as a string for whatever reason.
if(ok != NULL) *ok = stream.fail() == false;
// This returns the string that was created by the stream (e.g. what would
// have appeared on the terminal if stream were instead std::cout)
return stream.str();
}
回答7:
@Luna, what Wheaties mentioned is that the type of the template parameter T in your function template<class T> string toString(const T& t, bool *ok = NULL) {
should either be part of the list of datatypes or the type T should implement the ostream's << operator. Else the function would fail.
来源:https://stackoverflow.com/questions/3512685/a-template-class-in-c