220 36864 <28e80709-5ebb-44d2-b26d-22cafd681330@isocpp.org> article
Path: news.gmane.org!.POSTED!not-for-mail
From: Nicol Bolas <jmckesson@gmail.com>
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: String interpolation
Date: Sun, 11 Feb 2018 00:35:50 -0800 (PST)
Lines: 522
Approved: news@gmane.org
Message-ID: <28e80709-5ebb-44d2-b26d-22cafd681330@isocpp.org>
References: <356d5835-f1bf-4699-94f5-0b2d3d0b9c0e@isocpp.org>
 <CAMD6iD9aT26x8GQHnQL+kuj3Rq8fVQSfYYFtvTnFidkf6jU_ag@mail.gmail.com>
 <25CCF885-86AD-4D51-8F5C-C46376D34DE0@gmail.com> <4890431.TR9UepuQra@tjmaciei-mobl1>
 <CALvx3hac77b6Z=EOWzKqynALi1-352OvY0dnnOer8rN6tfa01g@mail.gmail.com> <1cdb6300-7397-46d7-bce9-62e6e8dac40b@isocpp.org>
 <CAC+0CCOSZHaTA=YPSDU8Add7mE_BYcYPRCmGW8TRPtZhdqL8Hw@mail.gmail.com>
 <4bce681e-e729-4124-9322-69291fdb6678@isocpp.org>
 <f5feb9a0-99d3-433a-ae46-af34c8d00a61@isocpp.org>
 <8e456af5-09c3-461d-8562-30df127e93af@isocpp.org>
 <bd24b702-025a-4b06-976b-559c779851e1@isocpp.org>
 <f63ed807-c5f6-4997-b03f-b4bc16a70982@isocpp.org>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: blaine.gmane.org
Mime-Version: 1.0
Content-Type: multipart/mixed; 
	boundary="----=_Part_4946_247154927.1518338150569"
X-Trace: blaine.gmane.org 1518338051 15732 195.159.176.226 (11 Feb 2018 08:34:11 GMT)
X-Complaints-To: usenet@blaine.gmane.org
NNTP-Posting-Date: Sun, 11 Feb 2018 08:34:11 +0000 (UTC)
To: ISO C++ Standard - Future Proposals <std-proposals@isocpp.org>
Original-X-From: std-proposals+bncBCEKFTV6ZUMBBZ4AQDKAKGQEJBU5KKI@isocpp.org Sun Feb 11 09:34:07 2018
Return-path: <std-proposals+bncBCEKFTV6ZUMBBZ4AQDKAKGQEJBU5KKI@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-ua0-f197.google.com ([209.85.217.197])
	by blaine.gmane.org with esmtp (Exim 4.84_2)
	(envelope-from <std-proposals+bncBCEKFTV6ZUMBBZ4AQDKAKGQEJBU5KKI@isocpp.org>)
	id 1ekn51-0002b3-IW
	for gclcip-std-proposals@m.gmane.org; Sun, 11 Feb 2018 09:33:47 +0100
Original-Received: by mail-ua0-f197.google.com with SMTP id b45sf8052947uad.10
        for <gclcip-std-proposals@m.gmane.org>; Sun, 11 Feb 2018 00:35:53 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=isocpp-org.20150623.gappssmtp.com; s=20150623;
        h=date:from:to:message-id:in-reply-to:references:subject:mime-version
         :x-original-sender:reply-to:precedence:mailing-list:list-id
         :list-post:list-help:list-archive:list-subscribe:list-unsubscribe;
        bh=3IMNqZshcPEPdF/XBOOcynNyLevKQoO6mUhx+Dwax+4=;
        b=M9+kaBZWt/Aw8VSrCGfVGMOmHVDf691z43n9KTzko1Dv+WtQPeP1lagISq3CNfDolY
         c7fwqzgb9Pc7TBYt6BkpBBTqdJC3hYoLHLuKMkUbTkwmPkcFtQMRN3UUHpzCFBbbdPeQ
         ar7WJJROGrwutmkK977TlyShCO3IAoxXPNhfiukx/4JK71/P65G/vducDyZXNPHsRGfV
         r7cYQG3cpPbw5kDgc+bAfWT9UWjgYgS7KabzQxIv3fs4AIazDva3eZ/A0xIDa5imTz/W
         qSmORUp7yODvwntTLYVOERVLTPfdIjxii3G4sCN96sZkGueMZIhVD7rV4kmv25QtSj/0
         tzVw==
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=20161025;
        h=date:from:to:message-id:in-reply-to:references:subject:mime-version
         :x-original-sender:reply-to:precedence:mailing-list:list-id
         :list-post:list-help:list-archive:list-subscribe:list-unsubscribe;
        bh=3IMNqZshcPEPdF/XBOOcynNyLevKQoO6mUhx+Dwax+4=;
        b=hxPMI1KXjuTdB6e+c3k9/SamxP8fWbeOwllxvB2rClw+N9XLI0XXAOJ5+gOb4FYXKG
         iYkQAEIXzNkqu6ISsXwabPPXYID84jU0H8WIo1RgPrftFiV2sETGZRMeH8DqbDPA0zgi
         ZjsFRYF1n0T4UcnROPpKJrql9k/Cxkrugmrmp/Wk0gwhlfiVHt6A/X6B3Ed/7Uo+in7Y
         AGrs/moPPb6JZTBuomjt5hCaenSyU9GQ1I6c/1nyV0wjLoSNdqR2RdefDKbyoHLJjhx0
         caPTgRLmPwlS4REeFuOwP6XLzkCx6sNCJMIzAfVqzB6lwsWmK9bZLIwJuMNH5M4Z2KDh
         7ZkQ==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20161025;
        h=x-gm-message-state:date:from:to:message-id:in-reply-to:references
         :subject:mime-version:x-original-sender:reply-to:precedence
         :mailing-list:list-id:x-spam-checked-in-group:list-post:list-help
         :list-archive:list-subscribe:list-unsubscribe;
        bh=3IMNqZshcPEPdF/XBOOcynNyLevKQoO6mUhx+Dwax+4=;
        b=mYXcAkxwSOh6+7OSoErEWH/kdMBcAXqQDNO78okPi8/8QgIBBtWPz0ux+SK11Fe2/N
         z49Q0Xe7Gltt/qaWQzeyzjqR8jOrCtq/icLArEQD120g3vIUKuAfqbX2+srcZGwm1dA3
         L7dbOmXimsRO5A4x1ePG5VD8HNu32i846/Nuj+R09FREJ7DF8gABjK4E96cGJvpnhTp2
         Gcc+9TuQ/QbVfkBo5ZhEEX4fh1R19m/ugjJVuSh4722m5l7m+QcQkfofmB3mposbMA97
         RDbejFD6fJ3LAuyjp9QpGFGJFXhIsl0cA2qPWakOjx0N9Cx+5d+a5SihbfU9Auq9gbMj
         exWg==
X-Gm-Message-State: APf1xPDmvU64t4c1ccKlSX6MdNTPjKZMwqAUSHKyjUsZUj9VYTLP7fmE
	VcHGIwpWcutRDZ9m0yznpKi/Qg==
X-Google-Smtp-Source: AH8x225+qt7zFZcTTnCsJGFbti4X/Ph+hQwQj7Xk9aFxMra2SbnwRSJKz17qAxLef26RG4b81zLPnQ==
X-Received: by 10.31.50.18 with SMTP id y18mr4194008vky.51.1518338152962;
        Sun, 11 Feb 2018 00:35:52 -0800 (PST)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.31.147.150 with SMTP id v144ls5818357vkd.2.gmail; Sun, 11 Feb
 2018 00:35:51 -0800 (PST)
X-Received: by 10.31.52.211 with SMTP id b202mr340834vka.9.1518338151167;
        Sun, 11 Feb 2018 00:35:51 -0800 (PST)
In-Reply-To: <f63ed807-c5f6-4997-b03f-b4bc16a70982@isocpp.org>
X-Original-Sender: jmckesson@gmail.com
Precedence: list
Mailing-list: list std-proposals@isocpp.org; contact std-proposals+owners@isocpp.org
List-ID: <std-proposals.isocpp.org>
X-Spam-Checked-In-Group: std-proposals@isocpp.org
X-Google-Group-Id: 399137483710
List-Post: <https://groups.google.com/a/isocpp.org/group/std-proposals/post>, <mailto:std-proposals@isocpp.org>
List-Help: <https://support.google.com/a/isocpp.org/bin/topic.py?topic=25838>, <mailto:std-proposals+help@isocpp.org>
List-Archive: <https://groups.google.com/a/isocpp.org/group/std-proposals/>
List-Subscribe: <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>,
 <mailto:std-proposals+subscribe@isocpp.org>
List-Unsubscribe: <mailto:googlegroups-manage+399137483710+unsubscribe@googlegroups.com>,
 <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>
Xref: news.gmane.org gmane.comp.lang.c++.isocpp.proposals:36864
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/36864>

------=_Part_4946_247154927.1518338150569
Content-Type: multipart/alternative; 
	boundary="----=_Part_4947_144716130.1518338150570"

------=_Part_4947_144716130.1518338150570
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable



On Saturday, February 10, 2018 at 9:38:20 PM UTC-5, Marcin Jaczewski wrote:
>
>
>
> On Saturday, February 10, 2018 at 8:37:45 PM UTC+1, Nicol Bolas wrote:
>>
>> On Saturday, February 10, 2018 at 1:39:45 PM UTC-5, Marcin Jaczewski=20
>> wrote:
>>>
>>> But it can easy check it, `_sql` is not string, if you pass string then=
=20
>>> it will be escaped before it is appended to finals string that is send =
to=20
>>> database.
>>> And how it will be exactly implemented? Like this:
>>> db.run(operator""_sql("select name as "_sql, a, ", age as "_sql, b, "fr=
om=20
>>> table where id =3D "_sql, c, ""_sql));
>>>
>>> This will call:
>>> sql_command operator""_sql(sql_command, std::string& a, sql_command, in=
t
>>> & b, sql_command, int& c, sql_command);
>>>
>>>
>> I see some value in the general approach, but allow me to redefine it in=
=20
>> a more coherent way.
>>
>> The token `F""` is treated a lot like we treat `...` pack expansions. Th=
e=20
>> `F` prefix performs a "string literal expansion" operation, transforming=
=20
>> the literal into a sequence of literals and identifiers extracted from t=
he=20
>> literal.
>>
>>
> And then wat result will be of:
> auto x =3D F"A {42} B"_z;
>
> If it work as pack expansion then it do not have meaning on its own.
>

You say that like it's a bad thing. Does `pack...` have meaning on its own?

The point of my idea is that it provides a sharp separation between the two=
=20
fundamental operations of "string interpolation". There's the "convert a=20
string literal into a bunch of smaller literals and variables" part. And=20
there's the "do something with that bunch of smaller literals and=20
variables."

By making part 1 into a pack expansion-like construct, it forces you to=20
make the way you want to process that expansion *explicit*. It also makes a=
=20
clear distinction between a UDL used for normal purposes and the system=20
used to process code.

For example, let's say I want to use interpolation to process a literal and=
=20
store all of the elements in a tuple. We can store each of the non-literal=
=20
parts easily enough. But what about the literal parts? You might say that a=
=20
`const char*` is good enough, but maybe I want it to be a `string_view`. To=
=20
do that with my system, it's as simple as:

tuple(F"some string {variable} other string"sv);

I have to write precisely *zero code* to make that work.

With your system, I have to write a function. Scratch that; I have to=20
create *two* functions. One function is the string fragment UDL, which does=
=20
exactly what `operator""sv` does. And the other is literally just `return=
=20
tuple(std::forward<Args>(args)...);`.

So I have to write two functions, and both of them are one-liners.

And if I want to do the exact same tuple building, only with `std::string`=
=20
instead of `string_view`, I have to write two functions. Again. One of them=
=20
will be *exactly identical* to the one paired with `string_view`.

Or I could just do:

tuple(F"some string {variable} other string"s);

No additional code needs to be written here. It Just Works(tm).

And look back at your `_sql` example. To me, a string with the `_sql`=20
literal suffix ought to be a compiled SQL statement, ready to be executed.=
=20
The syntax of the this statement shoudl be verified as valid.

But that's not the case with the `_sql` suffixes used on the string=20
fragments. While the total result of the interpolation is an SQL statement,=
=20
"select name as" is not valid SQL *by itself*. So what exactly is the=20
`_sql` suffix doing to these fragments? Some basic token recognition? Why=
=20
bother; the final concatenation process is what has to do all of the=20
serious validation work.

This separation between how a string fragment is processed and how the=20
aggregation is built is important. And the best way to achieve that=20
separation is to actually separate them.

I also find that my idea is more forward-looking. If we do get full=20
`constexpr` string support, then there's no reason why we shouldn't be able=
=20
to invoke the compiler's support for "string interpolation" on such a=20
string. Your idea is so heavily based on UDLs that it becomes difficult to=
=20
make it work on `constexpr` non-UDL strings. Why? Because your design=20
requires two parts: grammar to say "interpolate string" and a secondary=20
parameter that says "with this".

My design has grammar that says "interpolation string". The "with this"=20
part comes out through the regular rules of C++: explicit function calls.=
=20
That means we already have grammar to say "with this". All my design would=
=20
need to service `constexpr` strings is for the "interpolate string" grammar=
=20
to be something that can be applied to variables as well as literals.

Your design would require being able to apply UDLs to a `constexpr` string.

I would like if it work similar to:
> auto x =3D "A B"_z;
>
> It create new object with some type controlled by `_z` UDL.
>

I don't understand why you have such a need to have UDLs control this=20
process. We already have ways to take a sequence of values and aggregate=20
them into an object. It's called "calling a function with them".

What I find wrongheaded and/or confusing about your approach here is that=
=20
>> you apply the UDL *twice*, with two different meanings. The outer UDL is=
=20
>> about string concatenation. The inner UDL is about regular UDL stuff.
>>
>>
> As I based this on Marcel Kr=C3=BCger sugestion, he used normal string li=
terals=20
> as parameters but this prevent any meta programing with it.
>

It doesn't interfere with constexpr programming, though. Let's stop trying=
=20
to apply C++03 solutions to C++20.

This mean each parameter need be separate type. Question is what type? Some=
=20
> `std::string_literal<char, 'a', 'b', 'c'>`? But this will need adding=20
> header like for `std::initializer_list`. But I thought that better is app=
ly=20
> again same postfix for inner parts because you should already have contro=
l=20
> of this.
>

And if you want to apply a suffix that returns such a thing with my design,=
=20
you can. But there need not be a *direct* connection between how you=20
process the string fragments and how you apply the aggregation.

So the `_sql` simply does regular UDL stuff. How do you put all of these=20
>> together? That's the job of `db:run`. It gets a sequence of parameters;=
=20
>> some of those parameters are the results of the `_sql` UDL; others are j=
ust=20
>> generic values it will do with as it pleases.
>>
>> So doing standard "string interpolation" operations through iostreams=20
>> would look like this:
>>
>> std::stream_fmt(F"Hello, {recipient}!");
>>
>> =20
>
> This could work too, but it this better would be if `F` return normal=20
> object:
> genericFunc(fmt(F"Hello {name}"), fmt(F"Sth {x}")); //yours version
> genericFunc(F"Hello {name}"_fmt, F"Sth {x}"_fmt); //my version
>
> Overall I think this should be done this way because you will have better=
=20
> control over what semantic this string literal will have. In your case it=
=20
> all will depend on context.
> One drawback of my version is that without UDL `F"{a}"` have no meaning.
>

But you have less control over it, because you have this UDL issue. Your=20
method requires two different kinds of UDLs: a UDL for the purpose of=20
interpreting a literal (aka: what UDLs are for), and a "UDL" that acts as a=
=20
processing framework for an string interpolation sequence. Why do these two=
=20
things need to be spelled the same way?

Consider an `fmt` that uses iostreams. So you do this:

F"some string {variable} other {variable}"fmt;

And that's supposed to be converted into:

operator ""fmt(operator ""fmt("some string "), variable, operator ""fmt("=
=20
other "), variable);

But all of those inner "fmt" literals? They *don't do anything*. All they=
=20
do is return the string. It's the outer "fmt" call that creates the=20
`ostringstream` and outputs each object to it.

Any serious work spent processing the string fragments will be done by the=
=20
outer UDL, which is not really a UDL at all. You have two *fundamentally*=
=20
different things going on, but you're trying to pretend that they're the=20
same. They aren't.

--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/28e80709-5ebb-44d2-b26d-22cafd681330%40isocpp.or=
g.

------=_Part_4947_144716130.1518338150570
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>On Saturday, February 10, 2018 at 9:38:20 PM UTC-5=
, Marcin Jaczewski wrote:<blockquote class=3D"gmail_quote" style=3D"margin:=
 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div =
dir=3D"ltr"><br><br>On Saturday, February 10, 2018 at 8:37:45 PM UTC+1, Nic=
ol Bolas wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-l=
eft:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">On =
Saturday, February 10, 2018 at 1:39:45 PM UTC-5, Marcin Jaczewski wrote:<bl=
ockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-l=
eft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>But it can easy =
check it, `_sql` is not string, if you pass string then it will be escaped =
before it is appended to finals string that is send to database.<br>And how=
 it will be exactly implemented? Like this:<br><div style=3D"background-col=
or:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border=
-width:1px"><code><div><span style=3D"color:#000">db</span><span style=3D"c=
olor:#660">.</span><span style=3D"color:#000">run</span><span style=3D"colo=
r:#660">(</span><span style=3D"color:#008">operator</span><span style=3D"co=
lor:#080">&quot;&quot;</span><span style=3D"color:#000">_sql</span><span st=
yle=3D"color:#660">(</span><span style=3D"color:#080">&quot;select name as =
&quot;</span><span style=3D"color:#000">_sql</span><span style=3D"color:#66=
0">,</span><span style=3D"color:#000"> a</span><span style=3D"color:#660">,=
</span><span style=3D"color:#000"> </span><span style=3D"color:#080">&quot;=
, age as &quot;</span><span style=3D"color:#000">_sql</span><span style=3D"=
color:#660">,</span><span style=3D"color:#000"> b</span><span style=3D"colo=
r:#660">,</span><span style=3D"color:#000"> </span><span style=3D"color:#08=
0">&quot;from table where id =3D &quot;</span><span style=3D"color:#000">_s=
ql</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> c</=
span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#080">&quot;&quot;</span><span style=3D"color:#000">_s=
ql</span><span style=3D"color:#660">));</span></div></code></div><br>This w=
ill call:<br><div style=3D"background-color:rgb(250,250,250);border-color:r=
gb(187,187,187);border-style:solid;border-width:1px"><code><div><span style=
=3D"color:#000">sql_command </span><span style=3D"color:#008">operator</spa=
n><span style=3D"color:#080">&quot;&quot;</span><span style=3D"color:#000">=
_sql</span><span style=3D"color:#660">(</span><span style=3D"color:#000">sq=
l_command</span><span style=3D"color:#660">,</span><span style=3D"color:#00=
0"> std</span><span style=3D"color:#660">::</span><span style=3D"color:#008=
">string</span><span style=3D"color:#660">&amp;</span><span style=3D"color:=
#000"> a</span><span style=3D"color:#660">,</span><span style=3D"color:#000=
"> sql_command</span><span style=3D"color:#660">,</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#008">int</span><span style=3D"color:#=
660">&amp;</span><span style=3D"color:#000"> b</span><span style=3D"color:#=
660">,</span><span style=3D"color:#000"> sql_command</span><span style=3D"c=
olor:#660">,</span><span style=3D"color:#000"> </span><span style=3D"color:=
#008">int</span><span style=3D"color:#660">&amp;</span><span style=3D"color=
:#000"> c</span><span style=3D"color:#660">,</span><span style=3D"color:#00=
0"> sql_command</span><span style=3D"color:#660">);</span></div></code></di=
v><br></div></div></blockquote><div><br>I see some value in the general app=
roach, but allow me to redefine it in a more coherent way.<br><br>The token=
 `F&quot;&quot;` is treated a lot like we treat `...` pack expansions. The =
`F` prefix performs a &quot;string literal expansion&quot; operation, trans=
forming the literal into a sequence of literals and identifiers extracted f=
rom the literal.<br><br></div></div></blockquote><div><br>And then wat resu=
lt will be of:<br><div style=3D"background-color:rgb(250,250,250);border-co=
lor:rgb(187,187,187);border-style:solid;border-width:1px"><code><div><span =
style=3D"color:#008">auto</span><span style=3D"color:#000"> x </span><span =
style=3D"color:#660">=3D</span><span style=3D"color:#000"> F</span><span st=
yle=3D"color:#080">&quot;A {42} B&quot;</span><span style=3D"color:#000">_z=
</span><span style=3D"color:#660">;</span></div></code></div><br>If it work=
 as pack expansion then it do not have meaning on its own.<br></div></div><=
/blockquote><div><br>You say that like it&#39;s a bad thing. Does `pack...`=
 have meaning on its own?<br><br>The point of my idea is that it provides a=
 sharp separation between the two fundamental operations of &quot;string in=
terpolation&quot;. There&#39;s the &quot;convert a string literal into a bu=
nch of smaller literals and variables&quot; part. And there&#39;s the &quot=
;do something with that bunch of smaller literals and variables.&quot;<br><=
br>By making part 1 into a pack expansion-like construct, it forces you to =
make the way you want to process that expansion <i>explicit</i>. It also ma=
kes a clear distinction between a UDL used for normal purposes and the syst=
em used to process code.<br><br>For example, let&#39;s say I want to use in=
terpolation to process a literal and store all of the elements in a tuple. =
We can store each of the non-literal parts easily enough. But what about th=
e literal parts? You might say that a `const char*` is good enough, but may=
be I want it to be a `string_view`. To do that with my system, it&#39;s as =
simple as:<br><br><div style=3D"background-color: rgb(250, 250, 250); borde=
r-color: rgb(187, 187, 187); border-style: solid; border-width: 1px; overfl=
ow-wrap: break-word;" class=3D"prettyprint"><code class=3D"prettyprint"><di=
v class=3D"subprettyprint"><span style=3D"color: #000;" class=3D"styled-by-=
prettify">tuple</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">F</s=
pan><span style=3D"color: #080;" class=3D"styled-by-prettify">&quot;some st=
ring {variable} other string&quot;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">sv</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">);</span></div></code></div><br>I have to write precisely <=
i>zero code</i> to make that work.<br><br>With your system, I have to write=
 a function. Scratch that; I have to create <i>two</i> functions. One funct=
ion is the string fragment UDL, which does exactly what `operator&quot;&quo=
t;sv` does. And the other is literally just `return tuple(std::forward&lt;A=
rgs&gt;(args)...);`.<br><br>So I have to write two functions, and both of t=
hem are one-liners.<br><br>And if I want to do the exact same tuple buildin=
g, only with `std::string` instead of `string_view`, I have to write two fu=
nctions. Again. One of them will be <i>exactly identical</i> to the one pai=
red with `string_view`.<br><br>Or I could just do:<br><br><div style=3D"bac=
kground-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border=
-style: solid; border-width: 1px; overflow-wrap: break-word;" class=3D"pret=
typrint"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify">tuple</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">F</span><span style=3D"color: #080;" =
class=3D"styled-by-prettify">&quot;some string {variable} other string&quot=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">s</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">);</span></div></c=
ode></div><br>No additional code needs to be written here. It Just Works(tm=
).<br><br>And look back at your `_sql` example. To me, a string with the `_=
sql` literal suffix ought to be a compiled SQL statement, ready to be execu=
ted. The syntax of the this statement shoudl be verified as valid.<br><br>B=
ut that&#39;s not the case with the `_sql` suffixes used on the string frag=
ments. While the total result of the interpolation is an SQL statement, &qu=
ot;select name as&quot; is not valid SQL <i>by itself</i>. So what exactly =
is the `_sql` suffix doing to these fragments? Some basic token recognition=
? Why bother; the final concatenation process is what has to do all of the =
serious validation work.<br><br>This separation between how a string fragme=
nt is processed and how the aggregation is built is important. And the best=
 way to achieve that separation is to actually separate them.<br><br>I also=
 find that my idea is more forward-looking. If we do get full `constexpr` s=
tring support, then there&#39;s no reason why we shouldn&#39;t be able to i=
nvoke the compiler&#39;s support for &quot;string interpolation&quot; on su=
ch a string. Your idea is so heavily based on UDLs that it becomes difficul=
t to make it work on `constexpr` non-UDL strings. Why? Because your design =
requires two parts: grammar to say &quot;interpolate string&quot; and a sec=
ondary parameter that says &quot;with this&quot;.<br><br>My design has gram=
mar that says &quot;interpolation string&quot;. The &quot;with this&quot; p=
art comes out through the regular rules of C++: explicit function calls. Th=
at means we already have grammar to say &quot;with this&quot;. All my desig=
n would need to service `constexpr` strings is for the &quot;interpolate st=
ring&quot; grammar to be something that can be applied to variables as well=
 as literals.<br><br>Your design would require being able to apply UDLs to =
a `constexpr` string.<br><br></div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div dir=3D"ltr"><div>I would like if it work similar to:<br><div sty=
le=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);borde=
r-style:solid;border-width:1px"><code><div><span style=3D"color:#008">auto<=
/span><span style=3D"color:#000"> x </span><span style=3D"color:#660">=3D</=
span><span style=3D"color:#000"> </span><span style=3D"color:#080">&quot;A =
B&quot;</span><span style=3D"color:#000">_z</span><span style=3D"color:#660=
">;</span></div></code></div><br>It create new object with some type contro=
lled by `_z` UDL.<br></div></div></blockquote><div><br>I don&#39;t understa=
nd why you have such a need to have UDLs control this process. We already h=
ave ways to take a sequence of values and aggregate them into an object. It=
&#39;s called &quot;calling a function with them&quot;.<br><br></div><block=
quote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-le=
ft: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div></div><blockqu=
ote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1=
px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>What I find wronghead=
ed and/or confusing about your approach here is that you apply the UDL <i>t=
wice</i>, with two different meanings. The outer UDL is about string concat=
enation. The inner UDL is about regular UDL stuff.<br><br></div></div></blo=
ckquote><div><br>As I based this on Marcel Kr=C3=BCger sugestion, he used n=
ormal string literals as parameters but this prevent any meta programing wi=
th it.</div></div></blockquote><div><br>It doesn&#39;t interfere with const=
expr programming, though. Let&#39;s stop trying to apply C++03 solutions to=
 C++20.<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><div>This mean each parameter need be separate type. Question is w=
hat type? Some `std::string_literal&lt;char, &#39;a&#39;, &#39;b&#39;, &#39=
;c&#39;&gt;`? But this will need adding header like for `std::initializer_l=
ist`. But I thought that better is apply again same postfix for inner parts=
 because you should already have control of this.<br></div></div></blockquo=
te><div><br>And if you want to apply a suffix that returns such a thing wit=
h my design, you can. But there need not be a <i>direct</i> connection betw=
een how you process the string fragments and how you apply the aggregation.=
<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"=
><div></div></div></blockquote><blockquote class=3D"gmail_quote" style=3D"m=
argin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"=
><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0;margi=
n-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">=
<div>So the `_sql` simply does regular UDL stuff. How do you put all of the=
se together? That&#39;s the job of `db:run`. It gets a sequence of paramete=
rs; some of those parameters are the results of the `_sql` UDL; others are =
just generic values it will do with as it pleases.<br><br>So doing standard=
 &quot;string interpolation&quot; operations through iostreams would look l=
ike this:<br><br><div style=3D"background-color:rgb(250,250,250);border-col=
or:rgb(187,187,187);border-style:solid;border-width:1px"><code><div><span s=
tyle=3D"color:#000">std</span><span style=3D"color:#660">::</span><span sty=
le=3D"color:#000">stream_fmt</span><span style=3D"color:#660">(</span><span=
 style=3D"color:#000">F</span><span style=3D"color:#080">&quot;Hello, {reci=
pient}!&quot;</span><span style=3D"color:#660">);</span></div></code></div>=
</div><br></div></blockquote><div>=C2=A0<br><br>This could work too, but it=
 this better would be if `F` return normal object:<br><div style=3D"backgro=
und-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid=
;border-width:1px"><code><div><span style=3D"color:#000">genericFunc</span>=
<span style=3D"color:#660">(</span><span style=3D"color:#000">fmt</span><sp=
an style=3D"color:#660">(</span><span style=3D"color:#000">F</span><span st=
yle=3D"color:#080">&quot;Hello {name}&quot;</span><span style=3D"color:#660=
">),</span><span style=3D"color:#000"> fmt</span><span style=3D"color:#660"=
>(</span><span style=3D"color:#000">F</span><span style=3D"color:#080">&quo=
t;Sth {x}&quot;</span><span style=3D"color:#660">));</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#800">//yours version</span><span s=
tyle=3D"color:#000"><br>genericFunc</span><span style=3D"color:#660">(</spa=
n><span style=3D"color:#000">F</span><span style=3D"color:#080">&quot;Hello=
 {name}&quot;</span><span style=3D"color:#000">_fmt</span><span style=3D"co=
lor:#660">,</span><span style=3D"color:#000"> F</span><span style=3D"color:=
#080">&quot;Sth {x}&quot;</span><span style=3D"color:#000">_fmt</span><span=
 style=3D"color:#660">);</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#800">//my version</span></div></code></div><br>Overall I think=
 this should be done this way because you will have better control over wha=
t semantic this string literal will have. In your case it all will depend o=
n context.<br>One drawback of my version is that without UDL `F&quot;{a}&qu=
ot;` have no meaning.<br></div></div></blockquote><div><br>But you have les=
s control over it, because you have this UDL issue. Your method requires tw=
o different kinds of UDLs: a UDL for the purpose of interpreting a literal =
(aka: what UDLs are for), and a &quot;UDL&quot; that acts as a processing f=
ramework for an string interpolation sequence. Why do these two things need=
 to be spelled the same way?<br><br>Consider an `fmt` that uses iostreams. =
So you do this:<br><br><div style=3D"background-color: rgb(250, 250, 250); =
border-color: rgb(187, 187, 187); border-style: solid; border-width: 1px; o=
verflow-wrap: break-word;" class=3D"prettyprint"><code class=3D"prettyprint=
"><div class=3D"subprettyprint"><span style=3D"color: #000;" class=3D"style=
d-by-prettify">F</span><span style=3D"color: #080;" class=3D"styled-by-pret=
tify">&quot;some string {variable} other {variable}&quot;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">fmt</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">;</span></div></code></div><br>And =
that&#39;s supposed to be converted into:<br><br><div style=3D"background-c=
olor: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: s=
olid; border-width: 1px; overflow-wrap: break-word;" class=3D"prettyprint">=
<code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">operator</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #080;"=
 class=3D"styled-by-prettify">&quot;&quot;</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify">fmt</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">(</span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">operator</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> </span><span style=3D"color: #080;" class=3D"styled-by-prett=
ify">&quot;&quot;</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify">fmt</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
(</span><span style=3D"color: #080;" class=3D"styled-by-prettify">&quot;som=
e string &quot;</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">),</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> va=
riable</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span=
 style=3D"color: #008;" class=3D"styled-by-prettify">operator</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: #080;" class=3D"styled-by-prettify">&quot;&quot;</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify">fmt</span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #080;" c=
lass=3D"styled-by-prettify">&quot; other &quot;</span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">),</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> variable</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">);</span></div></code></div><br>But all of thos=
e inner &quot;fmt&quot; literals? They <i>don&#39;t do anything</i>. All th=
ey do is return the string. It&#39;s the outer &quot;fmt&quot; call that cr=
eates the `ostringstream` and outputs each object to it.<br><br>Any serious=
 work spent processing the string fragments will be done by the outer UDL, =
which is not really a UDL at all. You have two <i>fundamentally</i> differe=
nt things going on, but you&#39;re trying to pretend that they&#39;re the s=
ame. They aren&#39;t.<br></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/28e80709-5ebb-44d2-b26d-22cafd681330%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/28e80709-5ebb-44d2-b26d-22cafd681330=
%40isocpp.org</a>.<br />

------=_Part_4947_144716130.1518338150570--

------=_Part_4946_247154927.1518338150569--

.
