1

If we want to construct a complex string, say like this: "I have 10 friends and 20 relations" (where 10 and 20 are values of some variables) we can do it like this:

std::ostringstream os;
os << "I have " << num_of_friends << " friends and " << num_of_relations << " relations";

std::string s = os.str();

But it is a bit too long. If in different methods in your code you need to construct compound strings many times you will have to always define an instance of std::ostringstream elsewhere.

Is there a shorter way of doing so just in one line?

I created some extra code for being able to do this:

struct OstringstreamWrapper
{
     std::ostringstream os;
};

std::string ostream2string(std::basic_ostream<char> &b)
{
     std::ostringstream os;
     os << b;
     return os.str();
}

#define CreateString(x) ostream2string(OstringstreamWrapper().os << x)

// Usage:
void foo(int num_of_friends, int num_of_relations)
{
     const std::string s = CreateString("I have " << num_of_friends << " and " << num_of_relations << " relations");
}

But maybe there is simpler way in C++ 11 or in Boost?

Andrey Rubliov
  • 1,359
  • 2
  • 17
  • 24
  • Possible duplicate of [std::string formatting like sprintf](http://stackoverflow.com/questions/2342162/stdstring-formatting-like-sprintf) – moooeeeep Jan 26 '16 at 12:01
  • 1
    Also have a look at this: http://stackoverflow.com/q/10410023/1025391 – moooeeeep Jan 26 '16 at 12:01

2 Answers2

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

template<typename T, typename... Ts>
std::string CreateString(T const& t, Ts const&... ts)
{
    using expand = char[];

    std::ostringstream oss;
    oss << std::boolalpha << t;
    (void)expand{'\0', (oss << ts, '\0')...};
    return oss.str();
}

void foo(int num_of_friends, int num_of_relations)
{
    std::string const s =
        CreateString("I have ", num_of_friends, " and ", num_of_relations, " relations");
    std::cout << s << std::endl;
}

int main()
{
    foo(10, 20);
}

Online Demo

ildjarn
  • 62,044
  • 9
  • 127
  • 211
  • Thanks, that's great, I was just hoping there is a syntax using <<. – Andrey Rubliov Jan 26 '16 at 12:14
  • @user429775 : Not that I can think of, at least not without an ugly cast involved. In any case, this is implemented in terms of `operator<<`, so that's still all you need for your types to work here. – ildjarn Jan 26 '16 at 12:32
  • I have posted a question about how exactly this code works, here: http://stackoverflow.com/q/35232729/1025391 – moooeeeep Feb 05 '16 at 20:16
1

You could use Boost.Format:

#include <iostream>
#include <boost/format.hpp>

using boost::format;

int main()
{
    std::cout << boost::format("I have %1% friends and %2% relations")
        % num_of_friends % num_of_relations; 
}
  • Well, that's nice, but if you want to change one parameter, you need to change in two places: in %1% and in % num_of_friends. Also if you just print to stdout using << and want to change it to be saved in string, you have to change it completely using %. – Andrey Rubliov Jan 26 '16 at 12:09
  • 1
    You can use `%s` instead of numbered parameters if you want. –  Jan 26 '16 at 12:11
  • @user429775 If you want to change your “print to `std::cout`” code to “save it into a string” code with as minimal edits as possible, the solution is to use a `std::ostringstream` as shown in your question. What's the point? – 5gon12eder Jan 26 '16 at 12:52