Date: Thu, 19 Oct 2023 18:54:01 +0200
Hi Hadriel,
the 2. expression not only combined a plain string-literal with a F string, but also was separated in the middle of the expression.
Concatenating strings so far happens in phase 5, macro expansion in phase 4.
If we want to have preprocessor support inside the expressions in the curly braces, the expressions in the curly braces in the F strings have to be separated out of the string in phase 3 or between current phase 3 and phase 4.
So they would not be a string, but for example an internal macro __F and __X.
Phase 3.5 would convert
F"abs(a+b)={abs(a+b)}"
into
-> __F("abs(a+b)={}", abs(a+b))
In Phase 4 abs is replaced by its definition, e.g.
#define abs(x) (((x) < 0) ? -(x) : (x))
-> __F("abs(a+b)={}", (((a+b) < 0) ? -(a+b) : (a+b))
and by std::format
-> std::format("abs(a+b)={}", (((a+b) < 0) ? -(a+b) : (a+b))
There _could_ be a special to concatenate several __F or concatenate them with strings before replacing it with std::format. So this would be done inside phase 4, not like the other preprocessor string concatenations in phase 5.
If the implementation is done that way, the incomplete examples (with curly braces being closed in the next string), if they are allowed at all, could make difficulties in the __F/__X replacement in phase 3.5 and would need special rules for concatenation.
F"a+b={a" F"+b}" -> __F_last curly_brace_still_open("a+b={", a) __F_first_curly_brace_missing("}", +b)
And then in phase 4 __F_last_curly_brace_still_open and __F_first_curly_brace_missing could be combined as a perfect match.
So it could be possible.
One could also disallow incomplete F or X string literals or disallow concatenating them.
IMHO supporting preprocessor symbols inside the C++ expressions within the curly braces is more important than incomplete F/X string literals or preprocessor concatenation of them.
C++ expressions should work the same way as outside, and the preprocessor is a part of that.
F and X string literals are not actually string literals in the sense that they have to be interpolated usually at runtime. They are more like an abbreviation of std::format and one cannot reasonably expect them to be concatenatable. If they are, it is nice, but no existing code depends on it.
And one can also enable it later on with a follow-up proposal.
-----Ursprüngliche Nachricht-----
Von:Hadriel Kaplan <hkaplan_at_[hidden]>
Gesendet:Do 19.10.2023 10:52
Betreff:Re: [std-proposals] Supporting f-strings in C++: draft-R1
An:std-proposals_at_[hidden];
CC:Sebastian Wittmeier <wittmeier_at_[hidden]>;
> 2. "a+b={a" F"+b}"
That one's tough because the first one is a plain string-literal.
I personally feel we should not need to support it - that an F"" or X"" prefix is not _only_ an encoding indicator of its quoted-string.
That instead it's something more.
It's arguably also an "instruction" or even a macro invocation. So I don't think it's even logical to have a regular string-literal before an instruction, and expect the instruction to apply backwards
> 3. F"abs(a)={a" "bs(a)}"
That one can be made to work without too much difficulty. Again, whether it _should_ work I don't know.
> 4. the last example yes or no, even if abs is implemented as a macro?
In my next proposal, where everything moves into preprocessing stage-4, it will work even if `abs()` is a macro. Ie., both 3 and 4 will semantically be equivalent to this, and resolve the `abs()` macro correctly:
F"abs(a)={abs(a)}"
> Jens pointed out that tokenization and macro expansion happen before string concatenation, so at the very least 4. would definitely not fit to the current phases. Probably 3. neither with the initially separated abs symbol.
If we move everything into the preprocessor - which we would have to if we want macros to work inside the f/x-strings at all - then it can work. Because we'd have to perform some string-literal concatenation in the preprocessor anyway. And that concatenation would be done _before_ the macros within the string get replaced (because the macros won't be replaced until they're pulled _out_ of the string).
> Would a F string count as a single token string literal or as several tokens or kind of both?
We'd create two new preprocessing-tokens: an f-string-literal and x-string-literal. The lexer would generate those based on the F"" or X"". So each is a single preprocessing-token.
During preprocessing expansion, the preprocessor would expand/replace those preprocessing-tokens with others (i.e., per the results of expansion).
>From a C++ TU perspective, after preprocessing those original F"" or X"" tokens won't exist, and neither will their quoted-string contents. The TU will only see the same stuff it sees today, including a string-literal format-string that was generated by the expansion of the F"" or X"".
-hadriel
Received on 2023-10-19 16:54:02