C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Supporting f-strings in C++: draft-R1

From: Marcin Jaczewski <marcinjaczewski86_at_[hidden]>
Date: Fri, 20 Oct 2023 19:18:00 +0200
pt., 20 paź 2023 o 10:02 Hadriel Kaplan <hkaplan_at_[hidden]> napisał(a):
>
>
> Juniper Public
> > From: Marcin Jaczewski <marcinjaczewski86_at_[hidden] <mailto:marcinjaczewski86_at_[hidden]>>
> > Date: Thursday, October 19, 2023 at 8:28 PM
>
> > Now side tangent, as this could be a preprocessor function, what benefits
> > will it bring to basic C or even using C api in C++?
>
> Good question. I was not proposing nor expecting this change to be adopted by WG14 anytime soon, if ever.
>
> I know there's a preference to keep the two preprocessors the same, at least over time. And there's nothing in the proposed changes that could not also be implemented in the C-preprocessor, obviously.
>
> So yeah, we should think about what that would be useful for and how.
>
>
> > C `printf` will not switch from `%` to `{}`.
> > This brings me to the conclusion that `_X` should not be a "basic" operation
> > but a composition of lower level macro functions.
>
> Or it could lead to different conclusion: WG14 could define a new printfmt() function, similar to printf() but for which the format-string is that of std::print() et al.
>
> I'd argue that would be less confusing for programmers, faster for preprocessing stage, and less error-prone than trying to convert formats using macros.
>

Is preprocessor stage a bottleneck in compilation aside from
`#include`? Overall most cost will be similar to `_X` as needed to do
the same work.
And even if C would add new print family then not everybody could use
this new C function like freestanding,
or already compiled third party libraries that will not be updated but
use `%` like formats.

>
> > This could be used with iosteams:
> > #define FORMAT(A) << (A) <<
> > #define ARG(A)
> > #define BETTER_OUT(F) _PARSE_EXTRACT(F, FORMAT, ARG)
>
> > //usage
> > int i;
> > float j;
> > std::cout << BETTER_OUT("{i}{j}");
>
> > //expand to
> > std::cout << "" << (i) << "" << (j) << "";
>
>
> But how is that better than just one of these?:
>
> std::cout << F"{i}{j}";
> std::print(X"{i}{j}");
>
> -hadriel
>
>

Point was not that it is better but that it can be done and show its
near complete in use cases.
It simply is flexible enough to be used in other context too, in most
cases simple `_X` will work.



I thought about it more and came to the conclusion that it could
support dynamic format length too if macros will accept more args.
Additionally if we split `_PARSE_EXTRACT` into two components then we
will have a lot of elasticity.
Like:
```
// XSTR helper stringify that appends prefix and postfix to string
// to match the whole original format one
// like `XSTR(a) => u8"a"s` if the format was `u8" "s`
#define FORMAT(XSTR, A, ...)

#define ARG(XSTR, A, ...)


//only handle string parts left over after extraction of arguments of
string literal
#define _PARSE_EXTRACT_FORMAT(STR, FORMAT)
//only handle extracted arguments from string
#define _PARSE_EXTRACT_ARG(STR, ARG)
//combination of both former macros, exists for performance reason to
not duplicate work in simple cases
#define _PARSE_EXTRACT(STR, FORMAT, ARG) _PARSE_EXTRACT_FORMAT(STR,
FORMAT) _PARSE_EXTRACT_ARG(STR, ARG)
```

with definition like this we simply can make parsing repeated for arg format:
```
#define FORMAT_INNER(XSTR, A) XSTR({})
#define ARG_INNER(XSTR, A) ,A

#define FORMAT(XSTR, A, F) XSTR({:) _PARSE_EXTRACT_FORMAT(XSTR(F),
FORMAT_INNER) XSTR(})
#define ARG(XSTR, A, F) , A _PARSE_EXTRACT_ARG(XSTR(F), ARG_INNER)


_PARSE_EXTRACT("{a:.{b}.}{c:d}", FORMAT, ARG)

//expand to
""
"{:" "." "{}" "." "}" //from {a:.{b}.}
"{:" "d" "}" //from {c:d}
""
,a ,b //from {a:.{b}.}
,c //from {c:d}

```
I think this gives us enough power to handle probaby all use cases.

Received on 2023-10-20 17:18:13