220 36885 <305b7669-0744-473e-9715-807b7e8051b6@isocpp.org> article
Path: news.gmane.org!.POSTED!not-for-mail
From: florian.csdt@gmail.com
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: String interpolation
Date: Mon, 12 Feb 2018 08:15:33 -0800 (PST)
Lines: 704
Approved: news@gmane.org
Message-ID: <305b7669-0744-473e-9715-807b7e8051b6@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>
 <28e80709-5ebb-44d2-b26d-22cafd681330@isocpp.org>
 <52b86f0a-b3b9-455f-9d4d-0f6b15192c90@isocpp.org>
 <1e9a5468-6efa-48a2-87ce-6bdb6d5c4e83@isocpp.org>
 <750ecf62-9637-40f4-8585-e3be2780fb46@isocpp.org>
 <f8f4407b-ecf6-4a4a-b3f6-c65813e3f843@isocpp.org>
 <5b5435db-772e-4c38-8867-f6fbc66d7cec@isocpp.org>
 <5c51d89a-54b6-490b-87f2-09ed263d8322@isocpp.org>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: blaine.gmane.org
Mime-Version: 1.0
Content-Type: multipart/mixed; 
	boundary="----=_Part_9940_1758140889.1518452133069"
X-Trace: blaine.gmane.org 1518452039 28783 195.159.176.226 (12 Feb 2018 16:13:59 GMT)
X-Complaints-To: usenet@blaine.gmane.org
NNTP-Posting-Date: Mon, 12 Feb 2018 16:13:59 +0000 (UTC)
To: ISO C++ Standard - Future Proposals <std-proposals@isocpp.org>
Original-X-From: std-proposals+bncBC26HM4V3MIRBJX3Q3KAKGQE6QIE74Y@isocpp.org Mon Feb 12 17:13:55 2018
Return-path: <std-proposals+bncBC26HM4V3MIRBJX3Q3KAKGQE6QIE74Y@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-vk0-f70.google.com ([209.85.213.70])
	by blaine.gmane.org with esmtp (Exim 4.84_2)
	(envelope-from <std-proposals+bncBC26HM4V3MIRBJX3Q3KAKGQE6QIE74Y@isocpp.org>)
	id 1elGjR-0005f1-TO
	for gclcip-std-proposals@m.gmane.org; Mon, 12 Feb 2018 17:13:30 +0100
Original-Received: by mail-vk0-f70.google.com with SMTP id b195sf9140589vkf.8
        for <gclcip-std-proposals@m.gmane.org>; Mon, 12 Feb 2018 08:15:35 -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=pK9Gy/CrEgOpnqRzOm5K+nwzTc7UfW3Dvr4VXlnfQ7U=;
        b=NoRmkoLMgBMd/gPsQE2d4sTnxCjZHCfw0Kerwv98Kklm+YqiW99TIhXFiUYIlfFDpH
         //4ufm6jadsHj6arVwZnkvEENrjDBB4Z3FAEY5uY930XfThtrkY54OdXWa+MD/kYenf1
         O5D607Yx9SUyQw2ymga/S9zRLtMzqHRxiZ4gDuDliLkWRew83haWUsCiJq/EqrAsU8Mb
         /pk+Qqc7j5ECFxoqGRgkVSSphoRvt809jACJVdGltZM4mDW06v5ik/qG/6I+hnFZ1tIc
         u4fW+jlFlns+NxOA81bE9nOXCEzruMHs3NxtfwvOx1sU43syDtIdP/sxNDC2a8ItXyUh
         /arw==
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=pK9Gy/CrEgOpnqRzOm5K+nwzTc7UfW3Dvr4VXlnfQ7U=;
        b=U29HRAh3ySALH3UsXmV4gqqG65nw4bH5TFbX8x3CDtb4itvbr0/RJC8fefWPjm7Cbu
         2+AKWfj3cUK0HEisB7qE4JTzDorLqvrOc9X7GfobLgyUdxfeTh98frYR0P7Gv6W95lHl
         IZzJsi902rhEnOjmSgIsXHBjF9AaCnw09Caw5rBkQ6jzQ1v1Z1dRYv6wHQwSNBv+H/2f
         dlbJPF3JvAPHhFFkC/L1ncyavswDj6QJwE1826WcZ6RF1Mx2JszTgE0jIGTlwuTV/1C4
         OV4UV3eig4FhJ7M80zER/K1D3KDINp8go5ktEOtEUg5CZGmZASm5YkWvm7hrkYJM93Cj
         /L4A==
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=pK9Gy/CrEgOpnqRzOm5K+nwzTc7UfW3Dvr4VXlnfQ7U=;
        b=HrZE7li6mc89QntbUn742Xr/eyvdbJuZCyOUTFiGXyU+dh+fD9DlTTrDQQbr0f6xI6
         g/T1vh6dgxHDVnHZBc/KG2gsEgTMT0J9rWA01NlhltoppLH5VymtGAz1DBLwHQzZQJzv
         AuIqeXKHhdmRcTBtnfl2U0DiwyWQE0m1jVdj3w1GN4BYMV7iMCxHSs7ZNfyBc2B30A0s
         zCvRSO6C/OBj47Bj0MImTmuFmC+gpD5F2Ohf/lksP5mDloFDUQuAC4Lcb35wf6Yk+rOg
         WWMd+sunCw55BXgGsRgEy0fO0urxHhIQpKLpEsHVscadwqZFJ9bMczZDKJQsz2cY455M
         I/SA==
X-Gm-Message-State: APf1xPDbS8/EeUwYeY5pq3r0OhNMSreU1A0CdrPZbSBFYFnIBSfWtxf5
	F1//bWqADEGTzO/ckFRG69b48w==
X-Google-Smtp-Source: AH8x227jyeUYlf8zmibiDtx9eUOMb/Z6ZJp90Pl6noI6yHJYtFx2raK8pwkisKcMBB8H50I3DhzNSw==
X-Received: by 10.31.166.17 with SMTP id p17mr3654429vke.104.1518452135408;
        Mon, 12 Feb 2018 08:15:35 -0800 (PST)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.31.135.84 with SMTP id j81ls1976494vkd.6.gmail; Mon, 12 Feb
 2018 08:15:33 -0800 (PST)
X-Received: by 10.31.178.206 with SMTP id b197mr1083140vkf.11.1518452133565;
        Mon, 12 Feb 2018 08:15:33 -0800 (PST)
In-Reply-To: <5c51d89a-54b6-490b-87f2-09ed263d8322@isocpp.org>
X-Original-Sender: florian.csdt@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:36885
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/36885>

------=_Part_9940_1758140889.1518452133069
Content-Type: multipart/alternative; 
	boundary="----=_Part_9941_2001226193.1518452133071"

------=_Part_9941_2001226193.1518452133071
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable



Le lundi 12 f=C3=A9vrier 2018 16:45:41 UTC+1, Nicol Bolas a =C3=A9crit :
>
> On Monday, February 12, 2018 at 10:14:25 AM UTC-5, floria...@gmail.com=20
> wrote:
>>
>> Le lundi 12 f=C3=A9vrier 2018 15:56:12 UTC+1, Nicol Bolas a =C3=A9crit :
>>>
>>> On Monday, February 12, 2018 at 5:17:45 AM UTC-5, floria...@gmail.com=
=20
>>> wrote:
>>>>
>>>> Let me suggest something close to Nicol's solution, but not quite.
>>>>
>>>> The F"" operator returns a special type that could be like a simple=20
>>>> tuple (let's name it std::string_processing for now).
>>>>
>>>> Then the user can use it directly into its own functions.
>>>>
>>>>
>>>> auto column =3D "col"s;
>>>> auto table =3D "tab"sv;
>>>> auto req =3D sql(F"select {column} from {table};");
>>>>
>>>> // would be equivalent to:
>>>> auto req =3D sql(std::string_processing<const char[8]&, std::string&,=
=20
>>>> const char[7]&, std::string_view&, const char[2]&>("select ", column, =
"=20
>>>> from ", table, ";"));
>>>>
>>>> Now, if we want, we could also support UDL (but not mandatory) by=20
>>>> allowing to call UDL on the std::string_processing:
>>>>
>>>> auto column =3D "col"s;
>>>> auto table =3D "tab"sv;
>>>> auto req =3D F"select {column} from {table};"_sql;
>>>>
>>>> // would be equivalent to:
>>>> auto req =3D operator ""_sql (std::string_processing<const char[8]&, s=
td
>>>> ::string&, const char[7]&, std::string_view&, const char[2]&>("select =
"
>>>> , column, " from ", table, ";"));
>>>>
>>>> Now let's have some examples of it could be:
>>>>
>>>> Simple string concatenation would be simple
>>>> auto concatenated =3D F"{str1}{str2}{str3}"s;
>>>> // converted into an efficient concatenation of the 3 strings
>>>>
>>>> We could print it into an iostream if we want (but would be here only=
=20
>>>> for convenience on legacy code)
>>>> std::cout << F"{str1}{str2}\n";
>>>> // equivalent to:
>>>> std::cout << str1 << str2 << "\n";
>>>>
>>>> It could be implicitly convertible to a std::string (only if variables=
=20
>>>> are implicitly convertible to std::string)
>>>> std::string concatenated =3D F"{str1}{str2}";
>>>>
>>>> (No example with FMT as I don't know how it works, but I don't see any=
=20
>>>> reason for it not to be compatible with FMT.)
>>>>
>>>> And this would be constexpr-able.
>>>>
>>>> Now, formatting would require a bit more elaborated type that could=20
>>>> store formatting information.
>>>> But in the end, only the user will know what to do with it.
>>>> However, I would prefer *not* to embed formatting in such a type, just=
=20
>>>> to keep it simple. And use a library based solution when I really need=
=20
>>>> formatting.
>>>>
>>>> It has all the advantages of Nicol's solution, while being more=20
>>>> versatile.
>>>>
>>>
>>> I fail to see the versatility here, and it does not have all of the=20
>>> advantages of my method.
>>>
>>> Remember, in my version, UDLs only apply to the string fragments. In=20
>>> your version, you *cannot* apply UDLs to string fragments; the string=
=20
>>> fragments will be packed into your `string_processing` type as views or=
=20
>>> some such.
>>>
>>> Then there's ease of use. Let's see how to implement stream-based strin=
g=20
>>> concatenation with my method:
>>>
>>> template<typename ...Args>
>>> auto concat(Args ...&&args)
>>> {
>>>   std::ostringstream stream;
>>>   stream << ... << std::forward<Args>(args);
>>>   return std::move(stream).get();
>>> }
>>>
>>> Simple and obvious, a standard bit of C++17 variadic template=20
>>> programming.
>>>
>>> Now, how would you go about doing that with `string_processing`? That=
=20
>>> would require template metaprogramming:
>>>
>>> template<typename ...Args, size_t ...Ints>
>>> void concat_items(std::ostringstream &stream, std::string_processing<
>>> Args...> &&proc, std::index_sequence<Ints...>)
>>> {
>>>   stream << ... << get<Ints>(proc));
>>> }
>>>
>>> template<typename ...Args>
>>> auto concat(std::string_processing<Args...> &&proc)
>>> {
>>>   std::ostringstream stream;
>>>   concat_items(stream, std::move(proc), std::make_index_sequence<size
>>> ...(Args)>{});
>>>   return std::move(stream).get();
>>> }
>>>
>>> This isn't the hardest code to write in the world, but it is much more=
=20
>>> complex than the previous one. Also, perfect forwarding doesn't really =
work=20
>>> here.
>>>
>>> Also, the variadic version of `concat` can be used with stuff that isn'=
t=20
>>> the result of string interpolation. Or with multiple interpolated strin=
gs.=20
>>> And so forth. Whereas your `string_processing` type is a magic type tha=
t=20
>>> only the compiler can create. And we already have a type that does what=
=20
>>> `string_processing` does; it's called `tuple`.
>>>
>>> The *only advantage* your method has over mine is that it allows UDLs=
=20
>>> to define the aggregation operation. Why is this so important to so man=
y=20
>>> people?
>>>
>>>
>>
>> Well, my solution is more versatile in the following sense: the result i=
s=20
>> a plain object that can be stored in a variable, returned from a functio=
n.
>>
>
> tuple(F"interpolated {string}")
>
> Oh look, "a plain object that can be stored in a variable, returned from =
a=20
> function". It required a whole 7 characters more.
>
> "Versatility" typically refers to the ability to do more things with=20
> something. My way can be put into an object, but your way cannot be put=
=20
> into a function's parameters as separate values nearly as easily. Mine=20
> seems more versatile.
>
> You could envision functions to transform std::string_processing into=20
>> another std::string_processing easily.
>>
>> Moreover, I know that some proposals try to enable creating a parameter=
=20
>> pack from a tuple (like an operator... ).
>>
>
> And sadly, none of them have advanced or even received additional revised=
=20
> proposals. My way works just fine with C++ as it is.
>
> And even if we had that, most use-cases you don't need to pass the values=
=20
> around as a collective object. And if you did, you can make one trivially=
,=20
> as above.
>
> And again, it still doesn't deal with the fact that you lose perfect=20
> forwarding.
>
=20
I understand your point about creating a tuple from a parameter pack to be=
=20
able to do what is natural with my proposal. Fair enough.

However, I don't see how we lose perfect forwarding. I mean, if the=20
variable is a lvalue, it is stored as an lvalue reference, and if it is a=
=20
rvalue, it is stored as an rvalue reference.
This would be the exact same rules as for std::forward_as_tuple.


> With that in mind, the implementation of your concat function with my=20
>> approach would be exactly the same as with your approach (with a call to=
=20
>> "operator..." of std::string_processing ).
>>
>> And then, with only c++17 metaprogramming capabilities, you could also=
=20
>> use std::apply.
>>
>
> You cannot `apply` things to operators. Not without creating a lambda=20
> function that gets called with it.
>
=20
Why not? You can get the address of an operator, and this is a callable=20
object.


> The fact is, it's a *lot* easier in C++ as it currently stands to go from=
=20
> parameter pack of values to an object than it is to go from an object to =
a=20
> parameter pack of values. I wish that were not the case, but so long as i=
t=20
> is the case, parameter packs will remain the easier-to-use option.
>
=20
You have a point.=20


> UDL the aggregate is not important to me, but it was easy to include and=
=20
>> allows neat syntax (in my opinion).
>>
>
> But it makes it impossible to apply a UDL to the string fragments. And=20
> that's important if you do want to use template metaprogramming on string=
=20
> literals.
>

I'm not sure to see the use case here. When you use UDL, you want the whole=
=20
literal to be what you say it would be.
auto s =3D "something"s; // s is a string
auto sv =3D "some other"sv; // s is a string view
We are not interested in what is happening in the middle. I don't why it=20
should be different with string interpolation (or whatever the name is).

And with my proposal, you can always apply a function to every single=20
element, and this function can be a UDL if you really want.


To sum up, F"something" returning a parameter pack is probably the way to=
=20
go because of the current C++, but would not bring that much with a proper=
=20
C++.
And then, I think UDL should apply to the whole stuff and not its part.

Assuming operator F"" returns a parameter pack:
auto s =3D F"{args}..."s;
// equivalent to:
auto s =3D operator ""s(args...);

// If you want to apply a UDL to part of it:
operator ""s(F"{args}...")...
// would be equiavlent to:
operator ""s(args)...

--=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/305b7669-0744-473e-9715-807b7e8051b6%40isocpp.or=
g.

------=_Part_9941_2001226193.1518452133071
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>Le lundi 12 f=C3=A9vrier 2018 16:45:41 UTC+1, Nico=
l Bolas a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"margi=
n: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><di=
v dir=3D"ltr">On Monday, February 12, 2018 at 10:14:25 AM UTC-5, <a>floria.=
...@gmail.com</a> 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">Le lundi 12 f=C3=A9vrier 2018 15:56:12 UTC+1, Nicol Bolas a =C3=A9crit=
=C2=A0:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8e=
x;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">On Monday, =
February 12, 2018 at 5:17:45 AM UTC-5, <a>floria...@gmail.com</a> 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">Let me suggest someth=
ing close to Nicol&#39;s solution, but not quite.<br><br>The F&quot;&quot; =
operator returns a special type that could be like a simple tuple (let&#39;=
s name it std::string_processing for now).<br><br>Then the user can use it =
directly into its own functions.<br><br><br><div style=3D"background-color:=
rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-wi=
dth:1px"><code><div><span style=3D"color:#008">auto</span><span style=3D"co=
lor:#000"> column </span><span style=3D"color:#660">=3D</span><span style=
=3D"color:#000"> </span><span style=3D"color:#080">&quot;col&quot;</span><s=
pan style=3D"color:#000">s</span><span style=3D"color:#660">;</span><span s=
tyle=3D"color:#000"><br></span><span style=3D"color:#008">auto</span><span =
style=3D"color:#000"> table </span><span style=3D"color:#660">=3D</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#080">&quot;tab&quot;<=
/span><span style=3D"color:#000">sv</span><span style=3D"color:#660">;</spa=
n><span style=3D"color:#000"><br></span><span style=3D"color:#008">auto</sp=
an><span style=3D"color:#000"> req </span><span style=3D"color:#660">=3D</s=
pan><span style=3D"color:#000"> sql</span><span style=3D"color:#660">(</spa=
n><span style=3D"color:#000">F</span><span style=3D"color:#080">&quot;selec=
t {column} from {table};&quot;</span><span style=3D"color:#660">);</span><s=
pan style=3D"color:#000"><br><br></span><span style=3D"color:#800">// would=
 be equivalent to:</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#008">auto</span><span style=3D"color:#000"> req </span><span sty=
le=3D"color:#660">=3D</span><span style=3D"color:#000"> sql</span><span sty=
le=3D"color:#660">(</span><span style=3D"color:#000">std</span><span style=
=3D"color:#660">::</span><span style=3D"color:#000">string_processing</span=
><span style=3D"color:#660">&lt;</span><span style=3D"color:#008">con<wbr>s=
t</span><span style=3D"color:#000"> </span><span style=3D"color:#008">char<=
/span><span style=3D"color:#660">[</span><span style=3D"color:#066">8</span=
><span style=3D"color:#660">]&amp;,</span><span style=3D"color:#000"> 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"> <=
/span><span style=3D"color:#008">const</span><span style=3D"color:#000"> </=
span><span style=3D"color:#008">char</span><span style=3D"color:#660">[</sp=
an><span style=3D"color:#066">7</span><span style=3D"color:#660">]&amp;,</s=
pan><span style=3D"color:#000"> std</span><span style=3D"color:#660">::</sp=
an><span style=3D"color:#000">string_view</span><span style=3D"color:#660">=
&amp;,</span><span style=3D"color:#000"> </span><span style=3D"color:#008">=
const</span><span style=3D"color:#000"> </span><span style=3D"color:#008">c=
har</span><span style=3D"color:#660">[</span><span style=3D"color:#066">2</=
span><span style=3D"color:#660">]&amp;&gt;(</span><span style=3D"color:#080=
">&quot;select &quot;</span><span style=3D"color:#660">,</span><span style=
=3D"color:#000"> column</span><span style=3D"color:#660">,</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#080">&quot; from &quot;</spa=
n><span style=3D"color:#660">,</span><span style=3D"color:#000"> table</spa=
n><span style=3D"color:#660">,</span><span style=3D"color:#000"> </span><sp=
an style=3D"color:#080">&quot;;&quot;</span><span style=3D"color:#660">));<=
/span><span style=3D"color:#000"><br></span></div></code></div><br>Now, if =
we want, we could also support UDL (but not mandatory) by allowing to call =
UDL on the std::string_processing:<br><br><div style=3D"background-color:rg=
b(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-widt=
h:1px"><code><div><span style=3D"color:#008">auto</span><span style=3D"colo=
r:#000"> column </span><span style=3D"color:#660">=3D</span><span style=3D"=
color:#000"> </span><span style=3D"color:#080">&quot;col&quot;</span><span =
style=3D"color:#000">s</span><span style=3D"color:#660">;</span><span style=
=3D"color:#000"><br></span><span style=3D"color:#008">auto</span><span styl=
e=3D"color:#000"> table </span><span style=3D"color:#660">=3D</span><span s=
tyle=3D"color:#000"> </span><span style=3D"color:#080">&quot;tab&quot;</spa=
n><span style=3D"color:#000">sv</span><span style=3D"color:#660">;</span><s=
pan style=3D"color:#000"><br></span><span style=3D"color:#008">auto</span><=
span style=3D"color:#000"> req </span><span style=3D"color:#660">=3D</span>=
<span style=3D"color:#000"> F</span><span style=3D"color:#080">&quot;select=
 {column} from {table};&quot;</span><span style=3D"color:#000">_sql</span><=
span style=3D"color:#660">;</span><span style=3D"color:#000"><br><br></span=
><span style=3D"color:#800">// would be equivalent to:</span><span style=3D=
"color:#000"><br></span><span style=3D"color:#008">auto</span><span style=
=3D"color:#000"> req </span><span style=3D"color:#660">=3D</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#008">operator</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#080">&quot;&quot;</span><s=
pan style=3D"color:#000">_sql </span><span style=3D"color:#660">(</span><sp=
an style=3D"color:#000">std</span><span style=3D"color:#660">::</span><span=
 style=3D"color:#000">string_processing</span><span style=3D"color:#660">&l=
t;</span><span style=3D"color:#008">const</span><span style=3D"color:#000">=
 </span><span style=3D"color:#008">char</span><span style=3D"color:#660">[<=
/span><span style=3D"color:#066">8</span><span style=3D"color:#660">]&amp;,=
</span><span style=3D"color:#000"> std</span><span style=3D"color:#660">::<=
/span><span style=3D"color:#008">string</span><span style=3D"color:#660">&a=
mp;,</span><span style=3D"color:#000"> </span><span style=3D"color:#008">co=
nst</span><span style=3D"color:#000"> </span><span style=3D"color:#008">cha=
r</span><span style=3D"color:#660">[</span><span style=3D"color:#066">7</sp=
an><span style=3D"color:#660">]&amp;,</span><span style=3D"color:#000"> std=
</span><span style=3D"color:#660">::</span><span style=3D"color:#000">strin=
g_view</span><span style=3D"color:#660">&amp;,</span><span style=3D"color:#=
000"> </span><span style=3D"color:#008">const</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#008">char</span><span style=3D"color:#660=
">[</span><span style=3D"color:#066">2</span><span style=3D"color:#660">]&a=
mp;&gt;(</span><span style=3D"color:#080">&quot;select &quot;</span><span s=
tyle=3D"color:#660">,</span><span style=3D"color:#000"> column</span><span =
style=3D"color:#660">,</span><span style=3D"color:#000"> </span><span style=
=3D"color:#080">&quot; from &quot;</span><span style=3D"color:#660">,</span=
><span style=3D"color:#000"> table</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:#660">));</span><span style=3D"color:#000"><br=
></span></div></code></div><br>Now let&#39;s have some examples of it could=
 be:<br><br>Simple string concatenation would be simple<br><div style=3D"ba=
ckground-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:=
solid;border-width:1px"><code><div><span style=3D"color:#008">auto</span><s=
pan style=3D"color:#000"> concatenated </span><span style=3D"color:#660">=
=3D</span><span style=3D"color:#000"> F</span><span style=3D"color:#080">&q=
uot;{str1}{str2}{str3}&quot;</span><span style=3D"color:#000">s</span><span=
 style=3D"color:#660">;</span><span style=3D"color:#000"><br></span><span s=
tyle=3D"color:#800">// converted into an efficient concatenation of the 3 s=
trings</span><span style=3D"color:#000"><br></span></div></code></div><br>W=
e could print it into an iostream if we want (but would be here only for co=
nvenience on legacy code)<br><div style=3D"background-color:rgb(250,250,250=
);border-color:rgb(187,187,187);border-style:solid;border-width:1px"><code>=
<div><span style=3D"color:#000">std</span><span style=3D"color:#660">::</sp=
an><span style=3D"color:#000">cout </span><span style=3D"color:#660">&lt;&l=
t;</span><span style=3D"color:#000"> F</span><span style=3D"color:#080">&qu=
ot;{str1}{str2}\n&quot;</span><span style=3D"color:#660">;</span><span styl=
e=3D"color:#000"><br></span><span style=3D"color:#800">// equivalent to:</s=
pan><span style=3D"color:#000"><br>std</span><span style=3D"color:#660">::<=
/span><span style=3D"color:#000">cout </span><span style=3D"color:#660">&lt=
;&lt;</span><span style=3D"color:#000"> str1 </span><span style=3D"color:#6=
60">&lt;&lt;</span><span style=3D"color:#000"> str2 </span><span style=3D"c=
olor:#660">&lt;&lt;</span><span style=3D"color:#000"> </span><span style=3D=
"color:#080">&quot;\n&quot;</span><span style=3D"color:#660">;</span><span =
style=3D"color:#000"><br></span></div></code></div><br>It could be implicit=
ly convertible to a std::string (only if variables are implicitly convertib=
le to std::string)<br><div style=3D"background-color:rgb(250,250,250);borde=
r-color:rgb(187,187,187);border-style:solid;border-width:1px"><code><div><s=
pan style=3D"color:#000">std</span><span style=3D"color:#660">::</span><spa=
n style=3D"color:#008">string</span><span style=3D"color:#000"> concatenate=
d </span><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> F=
</span><span style=3D"color:#080">&quot;{str1}{str2}&quot;</span><span styl=
e=3D"color:#660">;</span><span style=3D"color:#000"><br></span></div></code=
></div><br>(No example with FMT as I don&#39;t know how it works, but I don=
&#39;t see any reason for it not to be compatible with FMT.)<br><br>And thi=
s would be constexpr-able.<br><br>Now, formatting would require a bit more =
elaborated type that could store formatting information.<br>But in the end,=
 only the user will know what to do with it.<br>However, I would prefer <b>=
not</b> to embed formatting in such a type, just to keep it simple. And use=
 a library based solution when I really need formatting.<br><br>It has all =
the advantages of Nicol&#39;s solution, while being more versatile.<br></di=
v></blockquote><div><br>I fail to see the versatility here, and it does not=
 have all of the advantages of my method.<br><br>Remember, in my version, U=
DLs only apply to the string fragments. In your version, you <i>cannot</i> =
apply UDLs to string fragments; the string fragments will be packed into yo=
ur `string_processing` type as views or some such.<br><br>Then there&#39;s =
ease of use. Let&#39;s see how to implement stream-based string concatenati=
on with my method:<br><br><div style=3D"background-color:rgb(250,250,250);b=
order-color:rgb(187,187,187);border-style:solid;border-width:1px"><code><di=
v><span style=3D"color:#008">template</span><span style=3D"color:#660">&lt;=
</span><span style=3D"color:#008">typename</span><span style=3D"color:#000"=
> </span><span style=3D"color:#660">...</span><span style=3D"color:#606">Ar=
gs</span><span style=3D"color:#660">&gt;</span><span style=3D"color:#000"><=
br></span><span style=3D"color:#008">auto</span><span style=3D"color:#000">=
 concat</span><span style=3D"color:#660">(</span><span style=3D"color:#606"=
>Args</span><span style=3D"color:#000"> </span><span style=3D"color:#660">.=
...&amp;&amp;</span><span style=3D"color:#000">args</span><span style=3D"col=
or:#660">)</span><span style=3D"color:#000"><br></span><span style=3D"color=
:#660">{</span><span style=3D"color:#000"><br>=C2=A0 std</span><span style=
=3D"color:#660">::</span><span style=3D"color:#000">ostringstream stream</s=
pan><span style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=
=A0 stream </span><span style=3D"color:#660">&lt;&lt;</span><span style=3D"=
color:#000"> </span><span style=3D"color:#660">...</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#660">&lt;&lt;</span><span style=3D"c=
olor:#000"> std</span><span style=3D"color:#660">::</span><span style=3D"co=
lor:#000">forward</span><span style=3D"color:#660">&lt;</span><span style=
=3D"color:#606">Args</span><span style=3D"color:#660">&gt;(</span><span sty=
le=3D"color:#000">args</span><span style=3D"color:#660">);</span><span styl=
e=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#008">return</span>=
<span style=3D"color:#000"> std</span><span style=3D"color:#660">::</span><=
span style=3D"color:#000">move</span><span style=3D"color:#660">(</span><sp=
an style=3D"color:#000">stream</span><span style=3D"color:#660">).</span><s=
pan style=3D"color:#008">get</span><span style=3D"color:#660">();</span><sp=
an style=3D"color:#000"><br></span><span style=3D"color:#660">}</span></div=
></code></div><br>Simple and obvious, a standard bit of C++17 variadic temp=
late programming.<br><br>Now, how would you go about doing that with `strin=
g_processing`? That would require template metaprogramming:<br><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">templ=
ate</span><span style=3D"color:#660">&lt;</span><span style=3D"color:#008">=
typename</span><span style=3D"color:#000"> </span><span style=3D"color:#660=
">...</span><span style=3D"color:#606">Args</span><span style=3D"color:#660=
">,</span><span style=3D"color:#000"> size_t </span><span style=3D"color:#6=
60">...</span><span style=3D"color:#606">Ints</span><span style=3D"color:#6=
60">&gt;</span><span style=3D"color:#000"><br></span><span style=3D"color:#=
008">void</span><span style=3D"color:#000"> concat_items</span><span style=
=3D"color:#660">(</span><span style=3D"color:#000">std</span><span style=3D=
"color:#660">::</span><span style=3D"color:#000">ostringstrea<wbr>m </span>=
<span style=3D"color:#660">&amp;</span><span style=3D"color:#000">stream</s=
pan><span style=3D"color:#660">,</span><span style=3D"color:#000"> std</spa=
n><span style=3D"color:#660">::</span><span style=3D"color:#000">string_pro=
cessing</span><span style=3D"color:#660">&lt;</span><span style=3D"color:#6=
06">Args</span><span style=3D"color:#660">...<wbr>&gt;</span><span style=3D=
"color:#000"> </span><span style=3D"color:#660">&amp;&amp;</span><span styl=
e=3D"color:#000">proc</span><span style=3D"color:#660">,</span><span style=
=3D"color:#000"> std</span><span style=3D"color:#660">::</span><span style=
=3D"color:#000">index_sequence</span><span style=3D"color:#660">&lt;</span>=
<span style=3D"color:#606">Ints</span><span style=3D"color:#660">...&gt;)</=
span><span style=3D"color:#000"><br></span><span style=3D"color:#660">{</sp=
an><span style=3D"color:#000"><br>=C2=A0 stream </span><span style=3D"color=
:#660">&lt;&lt;</span><span style=3D"color:#000"> </span><span style=3D"col=
or:#660">...</span><span style=3D"color:#000"> </span><span style=3D"color:=
#660">&lt;&lt;</span><span style=3D"color:#000"> </span><span style=3D"colo=
r:#008">get</span><span style=3D"color:#660">&lt;</span><span style=3D"colo=
r:#606">Ints</span><span style=3D"color:#660">&gt;(</span><span style=3D"co=
lor:#000">proc</span><span style=3D"color:#660">));</span><span style=3D"co=
lor:#000"><br></span><span style=3D"color:#660">}</span><span style=3D"colo=
r:#000"><br><br></span><span style=3D"color:#008">template</span><span styl=
e=3D"color:#660">&lt;</span><span style=3D"color:#008">typename</span><span=
 style=3D"color:#000"> </span><span style=3D"color:#660">...</span><span st=
yle=3D"color:#606">Args</span><span style=3D"color:#660">&gt;</span><span s=
tyle=3D"color:#000"><br></span><span style=3D"color:#008">auto</span><span =
style=3D"color:#000"> concat</span><span style=3D"color:#660">(</span><span=
 style=3D"color:#000">std</span><span style=3D"color:#660">::</span><span s=
tyle=3D"color:#000">string_processing</span><span style=3D"color:#660">&lt;=
</span><span style=3D"color:#606"><wbr>Args</span><span style=3D"color:#660=
">...&gt;</span><span style=3D"color:#000"> </span><span style=3D"color:#66=
0">&amp;&amp;</span><span style=3D"color:#000">proc</span><span style=3D"co=
lor:#660">)</span><span style=3D"color:#000"><br></span><span style=3D"colo=
r:#660">{</span><span style=3D"color:#000"><br>=C2=A0 std</span><span style=
=3D"color:#660">::</span><span style=3D"color:#000">ostringstream stream</s=
pan><span style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=
=A0 concat_items</span><span style=3D"color:#660">(</span><span style=3D"co=
lor:#000">stream</span><span style=3D"color:#660">,</span><span style=3D"co=
lor:#000"> std</span><span style=3D"color:#660">::</span><span style=3D"col=
or:#000">move</span><span style=3D"color:#660">(</span><span style=3D"color=
:#000">proc</span><span style=3D"color:#660">),</span><span style=3D"color:=
#000"> std</span><span style=3D"color:#660">::</span><span style=3D"color:#=
000">make_index_sequence</span><span style=3D"color:#660">&lt;</span><span =
style=3D"color:#000">size</span><span style=3D"color:#660">.<wbr>..(</span>=
<span style=3D"color:#606">Args</span><span style=3D"color:#660">)&gt;{});<=
/span><span style=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#00=
8">return</span><span style=3D"color:#000"> std</span><span style=3D"color:=
#660">::</span><span style=3D"color:#000">move</span><span style=3D"color:#=
660">(</span><span style=3D"color:#000">stream</span><span style=3D"color:#=
660">).</span><span style=3D"color:#008">get</span><span style=3D"color:#66=
0">();</span><span style=3D"color:#000"><br></span><span style=3D"color:#66=
0">}</span></div></code></div><br>This isn&#39;t the hardest code to write =
in the world, but it is much more complex than the previous one. Also, perf=
ect forwarding doesn&#39;t really work here.<br><br>Also, the variadic vers=
ion of `concat` can be used with stuff that isn&#39;t the result of string =
interpolation. Or with multiple interpolated strings. And so forth. Whereas=
 your `string_processing` type is a magic type that only the compiler can c=
reate. And we already have a type that does what `string_processing` does; =
it&#39;s called `tuple`.<br><br>The <i>only advantage</i> your method has o=
ver mine is that it allows UDLs to define the aggregation operation. Why is=
 this so important to so many people?<br></div><br></div></blockquote><div>=
<br></div><br><div>Well, my solution is more versatile in the following sen=
se: the=20
result is a plain object that can be stored in a variable, returned from
 a function.</div></div></blockquote><div><br><div style=3D"background-colo=
r:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-=
width:1px"><code><div><span style=3D"color:#000">tuple</span><span style=3D=
"color:#660">(</span><span style=3D"color:#000">F</span><span style=3D"colo=
r:#080">&quot;interpolated {string}&quot;</span><span style=3D"color:#660">=
)</span></div></code></div><br>Oh look, &quot;a plain object that can be st=
ored in a variable, returned from
 a function&quot;. It required a whole 7 characters more.<br><br>&quot;Vers=
atility&quot; typically refers to the ability to do more things with someth=
ing. My way can be put into an object, but your way cannot be put into a fu=
nction&#39;s parameters as separate values nearly as easily. Mine seems mor=
e versatile.<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>You could envision functions to transform std::string_process=
ing into another std::string_processing easily.</div><div><br></div><div>Mo=
reover, I know that some proposals try to enable creating a parameter pack =
from a tuple (like an operator... ).</div></div></blockquote><div><br>And s=
adly, none of them have advanced or even received additional revised propos=
als. My way works just fine with C++ as it is.<br><br>And even if we had th=
at, most use-cases you don&#39;t need to pass the values around as a collec=
tive object. And if you did, you can make one trivially, as above.<br><br>A=
nd again, it still doesn&#39;t deal with the fact that you lose perfect for=
warding.<br></div></div></blockquote><div>=C2=A0</div><div>I understand you=
r point about creating a tuple from a parameter pack to be able to do what =
is natural with my proposal. Fair enough.</div><div><br></div><div>However,=
 I don&#39;t see how we lose perfect forwarding. I mean, if the variable is=
 a lvalue, it is stored as an lvalue reference, and if it is a rvalue, it i=
s stored as an rvalue reference.</div><div>This would be the exact same rul=
es as for std::forward_as_tuple.</div><div> <br></div><blockquote class=3D"=
gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc so=
lid;padding-left: 1ex;"><div dir=3D"ltr"><div><br></div><blockquote class=
=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr"><div>With that in mind, the impleme=
ntation of your concat function with my approach would be exactly the same =
as with your approach (with a call to &quot;operator...&quot; of std::strin=
g_processing ).</div><div><br></div><div>And then, with only c++17 metaprog=
ramming capabilities, you could also use std::apply.<br></div></div></block=
quote><div><br>You cannot `apply` things to operators. Not without creating=
 a lambda function that gets called with it.<br></div></div></blockquote><d=
iv>=C2=A0</div><div>Why not? You can get the address of an operator, and th=
is is a callable object.</div><div><br></div><blockquote class=3D"gmail_quo=
te" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddi=
ng-left: 1ex;"><div dir=3D"ltr"><div><br>The fact is, it&#39;s a <i>lot</i>=
 easier in C++ as it currently stands to go from parameter pack of values t=
o an object than it is to go from an object to a parameter pack of values. =
I wish that were not the case, but so long as it is the case, parameter pac=
ks will remain the easier-to-use option.<br></div></div></blockquote><div>=
=C2=A0</div><div>You have a point. <br></div><div><br></div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #=
ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><br></div><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #c=
cc solid;padding-left:1ex"><div dir=3D"ltr"><div></div><div></div>UDL the a=
ggregate is not important to me, but it was easy to include and allows neat=
 syntax (in my opinion).<br></div></blockquote><div><br>But it makes it imp=
ossible to apply a UDL to the string fragments. And that&#39;s important if=
 you do want to use template metaprogramming on string literals.<br></div><=
/div></blockquote><div><br></div><div>I&#39;m not sure to see the use case =
here. When you use UDL, you want the whole literal to be what you say it wo=
uld be.</div><div><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: #008;" class=3D"styled-by-=
prettify">auto</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> s </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #080;" class=3D"styled-by-prettify">&quot;something&quo=
t;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">s</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #800;" class=3D"styled-by-prettify">// s is a string</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">auto</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> sv </span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #080;" class=3D"style=
d-by-prettify">&quot;some other&quot;</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify">sv</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-prettify"=
>// s is a string view</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br></span></div></code></div>We are not interested in what is =
happening in the middle. I don&#39;t why it should be different with string=
 interpolation (or whatever the name is).<br></div><div><br></div><div>And =
with my proposal, you can always apply a function to every single element, =
and this function can be a UDL if you really want.</div><div><br></div><div=
><br></div><div>To sum up, F&quot;something&quot; returning a parameter pac=
k is probably the way to go because of the current C++, but would not bring=
 that much with a proper C++.</div><div>And then, I think UDL should apply =
to the whole stuff and not its part.</div><div><br></div><div>Assuming oper=
ator F&quot;&quot; returns a parameter pack:<br></div><div><div style=3D"ba=
ckground-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); borde=
r-style: solid; border-width: 1px; overflow-wrap: break-word;" class=3D"pre=
ttyprint"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">auto</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> s </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> F</span><span style=3D"color: #080;" clas=
s=3D"styled-by-prettify">&quot;{args}...&quot;</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify">s</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><br></span><span style=3D"color: #800;" class=3D"styled-b=
y-prettify">// equivalent to:</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br></span><span style=3D"color: #008;" class=3D"styled-=
by-prettify">auto</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> s </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">operator</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span styl=
e=3D"color: #080;" class=3D"styled-by-prettify">&quot;&quot;</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify">s</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify">args</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">...);</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"><br><br></span><span style=3D"color: #800;" class=3D"s=
tyled-by-prettify">// If you want to apply a UDL to part of it:</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">operator</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #080;" class=3D"styled-by-prettify">&quot;&quot;</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify">s</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"style=
d-by-prettify">&quot;{args}...&quot;</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">)...</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"><br></span><span style=3D"color: #800;" class=3D"styled=
-by-prettify">// would be equiavlent to:</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">operator</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #080;" class=3D"style=
d-by-prettify">&quot;&quot;</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify">s</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">a=
rgs</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)...</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></=
div></code></div><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/305b7669-0744-473e-9715-807b7e8051b6%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/305b7669-0744-473e-9715-807b7e8051b6=
%40isocpp.org</a>.<br />

------=_Part_9941_2001226193.1518452133071--

------=_Part_9940_1758140889.1518452133069--

.
