How to construct a std::string with embedded values, i.e. "string interpolation"?

stochastic picture stochastic · Jun 22, 2016 · Viewed 35.1k times · Source

I want to create a string with embedded information. One way (not the only way) of achieving what I want is called string interpolation or variable substitution, wherein placeholders in a string are replaced with actual values.

In C, I would do something like this:

printf("error! value was %d but I expected %d",actualValue,expectedValue)

whereas if I were programming in python, I would do something like this:

"error! value was {0} but I expected {1}".format(actualValue,expectedValue)

both of these are examples of string interpolation.

How can I do this in C++?

Important Caveats:

  1. I know that I can use std::cout if I want to print such a message to standard output (not string interpolation, but prints out the kind of string I want):
cout << "error! value was " << actualValue << " but I expected "
<< expectedValue;

I don't want to print a string to stdout. I want to pass a std::string as an argument to a function (e.g. the constructor of an exception object).

  1. I am using C++11, but portability is potentially an issue, so knowing which methods work and don't work in which versions of C++ would be a plus.

Edit

  1. For my immediate usage, I'm not concerned about performance (I'm raising an exception for cryin' out loud!). However, knowing the relative performance of the various methods would be very very useful in general.

  2. Why not just use printf itself (C++ is a superset of C after all...)? This answer discusses some reasons why not. As far as I can understand, type safety is a big reason: if you put %d, the variable you put in there had better really be convertible to an integer, as that's how the function figures out what type it is. It would be much safer to have a method which uses compile-time knowledge of the actual type of the variables to be inserted.

Answer

Stephan Dollberg picture Stephan Dollberg · Jul 21, 2019

In C++20 you will be able to use std::format.

This will support python style formatting:

string s = std::format("{1} to {0}", "a", "b");

There is already an implementation available: https://github.com/fmtlib/fmt.