8

Even though in a template I can have any type, the function to_string does not work on basic strings:

for example:

std::string str("my string"); my_class(str); 

with this functor definition:

template<class valuetype> void operator()(valuetype value) { ... private_string_field = std::to_string(value); 

does not work. here is the error:

error: no matching function for call to ‘to_string(std::basic_string&)’

What is the best way to avoid it.

In advance, I request avoid linking to irrelevant questions just because of a few common keywords.

2
  • 2
    I am not going to go into whether it makes sense to not have to_string overloaded for std::string, but... why are you using it in the code above? The operator<< can take care of printing anything for which to_string is defined with a lower cost (no need to go through an intermediate std::string) Commented Mar 29, 2015 at 23:17
  • @DavidRodríguez-dribeas you are right. I just wanted to shorten the code so I put a cout. In fact, i need to store it somewhere and print it for later. inside a log file. Commented Mar 29, 2015 at 23:23

2 Answers 2

9

std::to_string only works on fundamental numeric types.

If you need a more generic function, boost::lexical_cast will work on many more types - effectively any type that can be sent to an iostream.

#include <boost/lexical_cast.hpp> ... private_string_field = boost::lexical_cast<std::string>(value); 
Sign up to request clarification or add additional context in comments.

Comments

3

There is no to_string for basic string. It would have nothing to do.

After Benjamin Lindley's suggestion I would consider the following design, use to_string but provide default template:

#include <iostream> #include <string> struct Type { explicit operator std::string() const{ return std::string("I am type"); } }; namespace std { template <typename T> string to_string(const T& value) { return string(value); } } int main(int argc, char **argv) { // this is what would be in class Type x; std::string private_string_field; private_string_field = std::to_string(42); std::cout << private_string_field << std::endl; private_string_field = std::to_string(x); std::cout << private_string_field << std::endl; return 0; } 

By default it tries to cast the operand to a string. This way custom types can provide their own conversion. Alternative design would be to internally use stringstream and operator<< for conversions, like this:

#include <iostream> #include <string> #include <sstream> struct Type { friend std::ostream& operator<<(std::ostream& out, const Type& value){ return out << "Type through operator<<"; } }; template <class T> std::string to_str(const T& value) { std::string ret; std::ostringstream ss; ss << value; ret = ss.str(); return ret; }; int main(int argc, char **argv) { // this is what would be in class Type x; std::string private_string_field; private_string_field = to_str(42); std::cout << private_string_field << std::endl; private_string_field = to_str(x); std::cout << private_string_field << std::endl; return 0; } 

5 Comments

This was a good analysis until the code in the question got drastically changed. :|
Now it handles strings correctly, but not much else.
@BenjaminLindley Could you please elaborate? Something else needs to be "castable" to std::string. Or you mean that for example int won't work? Well an alternative would be to write a template overload for to_string that would try to cast to string it by default. Not sure if it's a better design.
Yes, that's what I meant. It won't handle int or double or any of the other types for which there are std::to_string.overloads.
@BenjaminLindley I updated my answer. Not sure if it's better than Drew's (probably not) but at least it works for the cases you mentioned. Thanks for pointing it out.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.