views:

112

answers:

7

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

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

wheaties
@Wheaties, thanks, could you expalin more a little bit please
luna
Ugh! the formatting...
wheaties
+1  A: 

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

celavek
*Compilation* will no succeed if the stream doesn't know how to handle `T`. - But if `operator<<` is implemented for `T`, the implementation might choose to set a fail bit in the stream to signal that the conversion should be considered as failure at runtime. For built-in types, I'm not sure if conversion to string can fail at all from the stream's point of view (a possible out-of-memory situation would probably raise an exception?).
UncleBens
You are absolutely correct. I should be more careful on phrasing my answers.
celavek
+1  A: 

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.

bshields
@bshields: thanks
luna
+3  A: 

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.
James Curran
@James, thank you !!
luna
A: 

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();
}
Tyler McHenry
A: 

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

Gangadhar
+2  A: 

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.

Jon Purdy