views:

1421

answers:

4

I found the below code through Google. It almost does what I want it to do, except it doesn't provide a way to indicate the precision like '%.*f' does in C-type format strings. Also, it doesn't provide anything further than 5 decimal places. Am I going to have to stick with C strings and snprintf?

#include <string>
#include <sstream>
#include <iostream>

template <class T>
std::string to_string(T t, std::ios_base & (*f)(std::ios_base&))
{
  std::ostringstream oss;
  oss << f << t;
  return oss.str();
}

int main()
{
  std::cout<<to_string<double>(3.1415926535897931, std::dec)<<std::endl;
  return 0;
}
+1  A: 

C++ wouldn't be successful if it couldn't do something C could.

You need to check out manipulators.

If you want C-style formatting (which I do prefer, it's more terse), check out Boost.Format.

GMan
+2  A: 

Have you looked at Boost::format?

Edit: It's not entirely clear what you want. If you just want to write to a string, with formatting, you can use normal manipulators on a stringstream. If you want to use printf-style formatting strings, but retain type-safety, Boost::format can/will do that.

Jerry Coffin
+1  A: 

You want to use the setprecision function:

int main()
{
  std::cout<<std::setprecision(9)<<to_string<long>(3.1415926535897931, std::dec)<<std::endl;
  return 0;
}
1800 INFORMATION
That's not going to work actually. You're applying the manipulator to `std::cout` but pi is formatted inside to_string<long>(long t). Furthermore, since you passed pi as a `long`, it becomes `3L`.
MSalters
A: 

Taking the almost-correct answer (note that std::dec is redundant in this simple case):

int main()
{
  std::cout << std::setprecision(9) << std::dec << 3.1415926535897931 << std::endl;
  return 0;
}

However, if you wanted the to_string function to behave as desired, that's a bit more difficult. You'd need to pass setprecision(9) to the to_string<T> function, and it doesn't accept arguments of that type. You'd want a templated version:

template <class T, class F>
std::string to_string(T t, F f)
{
  std::ostringstream oss;
  oss << f << t;
  return oss.str();
}
int main()
{
  std::cout << to_string<double>(3.1415926535897931, std::setprecision(9)) << std::endl;
  return 0;
}

This works because you really didn't need std::dec in to_string. But if you needed to pass more manipulators, the simple solution is to add template <class T, class F1, class F2> std::string to_string(T t, F1 f1, F2 f2) etcetera. Technically this doesn't scale very well, but it's going to be so rare that you probably don't need it at all.

MSalters