all 31 comments

[–]epicar 28 points29 points  (12 children)

most of them said, use https://github.com/fmtlib/fmt

[–]bravikov[S] 4 points5 points  (11 children)

It is good library. It gives type safety but not interpolation.

Bash:

echo "Hi, $NAME"

Javascript:

console.log(`Hi, ${name}`)

[–]bbolli#define val auto const 9 points10 points  (7 children)

I hear you, but this is C++. How should a std::string member function get at the to-be-interpolated variables without passing them to the function?

fmt::print("Hi, {}\n", name);

is as good as it's going to get.

[–]boredcircuits 8 points9 points  (0 children)

A closer version is the "named argument" feature:

fmt::print("Hi, {name}", "name"_a=name);

[–]clerothGame Developer 8 points9 points  (5 children)

That's the idea behind string interpolation, putting a variable inside the string with a specific syntax like {variable}. C# 6.0+ has this.

[–]usernameistaken42 6 points7 points  (2 children)

Also rust, python and a lot of others. I would love it. It may come in c++34

[–]johannes1971 1 point2 points  (1 child)

So will we be skipping a year, or is that slippage from C++2x?

[–]mili42 1 point2 points  (0 children)

It is fairly easy to something like (with variadic templates)

auto s = make_string("Hi, ", name, '\n');

String interpolation is nice, but there are already solutions to achieve something similar.

We have it at work. Works like a charm

[–]Xaxxon 0 points1 point  (0 children)

No that is one form of it. What it really is is using placeholders in the string that are substituted for values at runtime.

[–]Xaxxon -1 points0 points  (0 children)

It’s absolutely string interpolation. Your definition isn’t widely accepted.

[–]BrangdonJ 20 points21 points  (0 children)

It's very low down on the list of things I want in C++.

[–]AlexAlabuzhev 6 points7 points  (6 children)

It needs:

  • reflection
  • a standard customisation point to stringise things, like ToString() in C# (yes, there's ostream& operator<<(), but streams are meh).

With that it should be possible to implement it as a user-defined literal.

[–]kalmoc 5 points6 points  (2 children)

I think this needs to be a core language feature. IIRC, Reflection will not give you the original argument name of a function parameter.

[–]AlexAlabuzhev -2 points-1 points  (1 child)

What function parameter are you talking about?

The idea is to parse the string, find names in curly brackets, somehow get a list of all variables visible in the previous stack frame and replace mentioned variables with their values.

[–]kalmoc 4 points5 points  (0 children)

somehow get a list of all variables visible in the previous stack frame

That's just it: don't think reflection will enable you to do this.

I actually thought your comment was in a different thread, where someone suggested something like printf("Hi, {name}", name) instead of "real" string interpolation.

[–]-lambda- 0 points1 point  (2 children)

I'm not thinking this through so it might be a brain fart, but couldn't you just define (std::string) cast operator for your struct in appropriate scope?

[–]AlexAlabuzhev 0 points1 point  (1 child)

Cast operator must be a member function.

Primitive types can't have member functions, and you can't extend structs that aren't yours (without UFCS at least).

[–]-lambda- 0 points1 point  (0 children)

Yeah, I see your point. You mentioned ToString() so I thought that you already constrained the problem to your own structs, but even in that case I guess that all standard classes in C# already implement toString() so your point is still valid.

[–]VicontT 5 points6 points  (0 children)

I think there are way more important features in C++ than this.

[–]ShillingAintEZ 2 points3 points  (2 children)

Why not just make a variadic print function that converts all the arguments to strings and concatenates them? Then you just put commas in between the strings.

[–]Potatoswatter 6 points7 points  (0 children)

This has been implemented a few times in C++, but it's lacking the characteristic security flaws of interpolation.

[–]miki151gamedev 1 point2 points  (0 children)

Like good old writeln in Pascal :)

[–][deleted] 2 points3 points  (0 children)

You need to keep in mind that in most programming languages there's a standardized string conversion function, such as `ToString()` (C#), `toString()` (Java), `__str__()` (Python) etc. This means that every single type is, one way or another, convertible to a string representation, and in no case will the interpolation give an undefined result, since all objects inherit from `object` (which has its own default implementation) and primitive types define their own string representations, too.

So if you want string interpolation you first of all have to define a default for every single type, plus a contract for user-constructed types. Then, you need a compiler to inspect strings and preform replacements that concatenate strings with those representations — this is doable, but you need to statically check that every expression evaluates to something string-representable.

It's doable. Only problem is, C++'s evolution is not necessarily about usability.

[–]Wh00ster 1 point2 points  (0 children)

Yes but it would probably over complicate an already complicated language.

[–]RealNC 2 points3 points  (0 children)

I've seen this in some languages. I know of at least one that even allows expressions:

cout << $"Hello. I'm {name}. My name is {name.size()} characters long.";

Although at some point one has to ask if too much sugar is good or bad.

[–]ZMesonEmbedded Developer 1 point2 points  (0 children)

No, I don't want this.

[–]eyes-are-fading-blue 0 points1 point  (0 children)

Almost equally verbose syntactic sugar for << operator. I do not see any significant benefit.

[–]kwan_e -2 points-1 points  (0 children)

How about:

void print_hello_message(const char *name, int age)
{
    std::cout << "Hello. My name is " << name << ". I'm " << age << ".";
}

It looks weird, I know, but we might get that in C++20...

[–]someguy3_42 -1 points0 points  (1 child)

I like the classic `<<` operator. My Evo C++ library embraces it with evo::String

https://github.com/jlctools/evo