220 36901 <0e0876bb-7a44-45ff-ab9b-6443e78ea59c@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: Tue, 13 Feb 2018 08:35:49 -0800 (PST)
Lines: 611
Approved: news@gmane.org
Message-ID: <0e0876bb-7a44-45ff-ab9b-6443e78ea59c@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>
 <305b7669-0744-473e-9715-807b7e8051b6@isocpp.org>
 <0ceb2063-d7b6-4cb8-8c5c-c63aceb5b549@isocpp.org>
 <d26b85c2-707b-49a5-a007-617027506dd1@isocpp.org>
 <41b87b07-1a91-4bca-ba00-5734c09dbe77@isocpp.org>
 <ef8fbc4c-08c0-409e-815b-28e161101231@isocpp.org>
 <1a7f714d-4a91-4a95-8da4-0c688d18c4c4@isocpp.org>
 <5f8efcc0-f4e9-4518-abe5-5fffeab55083@isocpp.org>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: blaine.gmane.org
Mime-Version: 1.0
Content-Type: multipart/mixed; 
	boundary="----=_Part_5991_505544240.1518539749571"
X-Trace: blaine.gmane.org 1518539666 30899 195.159.176.226 (13 Feb 2018 16:34:26 GMT)
X-Complaints-To: usenet@blaine.gmane.org
NNTP-Posting-Date: Tue, 13 Feb 2018 16:34:26 +0000 (UTC)
Cc: florian.csdt@gmail.com
To: ISO C++ Standard - Future Proposals <std-proposals@isocpp.org>
Original-X-From: std-proposals+bncBCEKFTV6ZUMBBZ5HRTKAKGQEFKHRYGA@isocpp.org Tue Feb 13 17:34:21 2018
Return-path: <std-proposals+bncBCEKFTV6ZUMBBZ5HRTKAKGQEFKHRYGA@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+bncBCEKFTV6ZUMBBZ5HRTKAKGQEFKHRYGA@isocpp.org>)
	id 1eldWi-0005kL-4R
	for gclcip-std-proposals@m.gmane.org; Tue, 13 Feb 2018 17:33:52 +0100
Original-Received: by mail-vk0-f70.google.com with SMTP id o13sf11241026vkc.22
        for <gclcip-std-proposals@m.gmane.org>; Tue, 13 Feb 2018 08: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:cc: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=LgWfkOoDqwJCpdkUthkVTQunpxiTyKYfeAYfjk6eaAo=;
        b=laF8yICcEEvzDWisPDkVzOxVhHf+7qTMUC8yVdTR7WdPyE1kWz82SoAnZWpRydJBg/
         I0Ra2wgjwRYmIjVElAAlRu38Qrxr30yMbqSVydK5zCnTO8iM3h6rG5Qf96u5JdHK8M2m
         E0K1+NhO4aE54DeGm5A9RpZUAR9BPK5t/KZrHv6w3an/rTZGnh5+wQw2F8cM/n0y5DQS
         qIO1CUnvIfZ0LUooJxvinHm4Q6RGgqxjOBKxn6jlBc3vLIEXdrHDz67szVnlX6HFap+Y
         Vum441XhNgI5g/Wv7CXC/GjDwbGePD2FYHS7Gm5Dw1fzZ5PjCkj6N0EAdoeACtRXhlTV
         LXWA==
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=20161025;
        h=date:from:to:cc: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=LgWfkOoDqwJCpdkUthkVTQunpxiTyKYfeAYfjk6eaAo=;
        b=QxKBDnbXE1bY+XeZC0Go7f7CZTzat2oyFkLqGHCoQxQlShz87Fp3F6wAHdJ11otlHL
         rozuxXNRo+bTsnsjCExNn1CP23ggfqHXhQ2QjQbs4mq+13+vVIlKd60c408bDyBrCpfU
         ygYjI40gQcs4W2Ri3a9EFg8Igi15DG8tMCkct80JvG43ylBrThsPTS8m0fkv2KM4rmic
         IPgkdGsruJKKBVH46PizlGXZ+DHcKVaj7AWsn4fb+gISsiWkZRHkt1Z1P1XgTSYZSau0
         6BVLZzASUJ0bSVqJpnfKFMyDWZO5m5feUP0wDAhzI9gcqS+J/yOH7ErheGtYbgaxzy5c
         QHtg==
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:cc: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=LgWfkOoDqwJCpdkUthkVTQunpxiTyKYfeAYfjk6eaAo=;
        b=VAhKF1bRZXan56c8/p/2mv0FVjqZJG2ShmgQK1mFvPM0NgT2Mop3rmdmklZZbyL7CN
         5q32bxV19S99vpv2UNd+rTrX3kN9Qyrr2UDon2pniIb4DHBCW4+7VnnoxwfMBmGN1cz/
         4cqrDBI/fiaKeeXW5CV6feZ1Q4ui8+qiBstojgMQOMmFi5IkQWmxIrOcJcOF596blJVP
         iJrrmb3RvQFoaJqDjMG46FaZ8Vc7vWsdr565ynvNxat/LHwlmi1kwTcGyPfz80CC+VMr
         4hzy4+mLHr1eqsaXDzrty1h/wAlHbl3z9pc1m4ckoKfchZMuI1k55X2pkZfUkGh2IUoO
         vi0A==
X-Gm-Message-State: APf1xPDaAncBH6Qw5sdklf13Lj9iB+IwslBht8qvI5eT1mK86BseOsvw
	FmT6DH09Ofz8+R1W/b7re9WRFA==
X-Google-Smtp-Source: AH8x225UPLixX/yiKuA15Agg4KrpeptFevlZcA4xNToz+mICWBF3gn33TS7Lq+Bl0mg8y4KSzwLKHg==
X-Received: by 10.31.148.15 with SMTP id w15mr850412vkd.44.1518539752749;
        Tue, 13 Feb 2018 08:35:52 -0800 (PST)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.31.158.3 with SMTP id h3ls8919347vke.11.gmail; Tue, 13 Feb
 2018 08:35:50 -0800 (PST)
X-Received: by 10.31.157.18 with SMTP id g18mr156518vke.2.1518539750235;
        Tue, 13 Feb 2018 08:35:50 -0800 (PST)
In-Reply-To: <5f8efcc0-f4e9-4518-abe5-5fffeab55083@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:36901
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/36901>

------=_Part_5991_505544240.1518539749571
Content-Type: multipart/alternative; 
	boundary="----=_Part_5992_217892087.1518539749572"

------=_Part_5992_217892087.1518539749572
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

On Tuesday, February 13, 2018 at 4:50:00 AM UTC-5, floria...@gmail.com=20
wrote:
>
> Le mardi 13 f=C3=A9vrier 2018 07:28:45 UTC+1, Nicol Bolas a =C3=A9crit :
>>
>> On Monday, February 12, 2018 at 4:08:37 PM UTC-5, floria...@gmail.com=20
>> wrote:
>>>
>>> Le lundi 12 f=C3=A9vrier 2018 21:11:14 UTC+1, Nicol Bolas a =C3=A9crit =
:
>>>>
>>>> On Monday, February 12, 2018 at 12:43:41 PM UTC-5, floria...@gmail.com=
=20
>>>> wrote:
>>>>>
>>>>> Le lundi 12 f=C3=A9vrier 2018 17:56:48 UTC+1, Nicol Bolas a =C3=A9cri=
t :
>>>>>>
>>>>>> On Monday, February 12, 2018 at 11:15:33 AM UTC-5,=20
>>>>>> floria...@gmail.com wrote:
>>>>>>
>>>>> 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=
=20
>>>>>>>>> also use std::apply.
>>>>>>>>>
>>>>>>>>
>>>>>>>> You cannot `apply` things to operators. Not without creating a=20
>>>>>>>> lambda function that gets called with it.
>>>>>>>>
>>>>>>> =20
>>>>>>> Why not? You can get the address of an operator, and this is a=20
>>>>>>> callable object.
>>>>>>>
>>>>>>
>>>>>> You can only get the address of a single overload of an operator.=20
>>>>>> Remember: the whole idea is that you're dealing with a sequence of=
=20
>>>>>> variables of different types. So the second parameter to the operato=
r has=20
>>>>>> to be of different types for different invocations of the operator.
>>>>>>
>>>>>
>>>>> This is another quirk of C++ that should be fixed.
>>>>>
>>>>
>>>> Which incidentally is yet another proposal (lifting lambdas) that=20
>>>> stalled.
>>>>
>>>> The fact is, it's a *lot* easier in C++ as it currently stands to go=
=20
>>>>>>>> from parameter pack of values to an object than it is to go from a=
n object=20
>>>>>>>> to a parameter pack of values. I wish that were not the case, but =
so long=20
>>>>>>>> as it is the case, parameter packs will remain the easier-to-use o=
ption.
>>>>>>>>
>>>>>>> =20
>>>>>>> You have a point.=20
>>>>>>>
>>>>>>>
>>>>>>>> UDL the aggregate is not important to me, but it was easy to=20
>>>>>>>>> include and allows neat syntax (in my opinion).
>>>>>>>>>
>>>>>>>>
>>>>>>>> But it makes it impossible to apply a UDL to the string fragments.=
=20
>>>>>>>> And that's important if you do want to use template metaprogrammin=
g on=20
>>>>>>>> string literals.
>>>>>>>>
>>>>>>>
>>>>>>> I'm not sure to see the use case here. When you use UDL, you want=
=20
>>>>>>> the whole 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=
=20
>>>>>>> why it should be different with string interpolation (or whatever t=
he name=20
>>>>>>> is).
>>>>>>>
>>>>>>
>>>>>> Because not all of the "literal" is actually a literal anymore.=20
>>>>>> That's the whole point of string interpolation: you're taking a lite=
ral and=20
>>>>>> you're augmenting it with some non-literal data. Potentially=20
>>>>>> *runtime* non-literal data. It isn't a literal anymore, so the UDL=
=20
>>>>>> suffix can't apply to the aggregate. It can only apply to the indivi=
dual=20
>>>>>> literal fragments of the string.
>>>>>>
>>>>>
>>>>> Here, I don't care if it's called a literal, or if we invent a new=20
>>>>> name for this concept that appeared to match the concept of literal w=
hen=20
>>>>> "string interpolation" was not a thing.
>>>>> I'm more interested in the final syntax as the end user will see it.
>>>>>
>>>>> And I would prefer concatenate like this:
>>>>> auto s =3D F"{str1}{str2}{str3}"s;
>>>>> than this:
>>>>> auto s =3D std::concat(F"{str1}{str2}{str3}");
>>>>>
>>>>> The first one looks more natural in my opinion.
>>>>>
>>>>
>>>> It only looks more natural for the trivial cases. Consider what=20
>>>> `std::concat` would look like. It creates an `ostringstream`, applies =
it to=20
>>>> each parameter, and moves its result out. Why pick `ostringstream`? Wh=
y not=20
>>>> allow the user to decide which kind of stream to use and therefore whi=
ch=20
>>>> resulting string type to build?
>>>>
>>>
>>> I never said this should work only with UDL. I just said that I think i=
t=20
>>> is more natural if UDL worked like that.
>>> But I really think the user should keep control over what can be done=
=20
>>> with this syntax.
>>> So I totally agree with you: users should be able to call their own=20
>>> functions with it.
>>>
>>> And then, even considering F"{str1}{str2}{str3}"s for concatenating, I=
=20
>>> never mentionned std::ostringstream, I just said converted into an=20
>>> efficient way of concatenating strings.
>>> In that case, I just considered that when we use operator ""s, we want =
a=20
>>> std::string.
>>>
>>
>> You say that the literal `s` means you want a `std::string`. But that's=
=20
>> not enough information, because you now have to define how to *get* a=20
>> `std::string` from values that aren't `std::string`. That's why you need=
=20
>> more information than a mere literal can provide.
>>
>> There are many ways to get a std::string from an interpolated string.=20
>> Your `operator""s` will only be doing one of them. That mechanism will b=
e=20
>> *fixed*. Inflexible. Unchangeable.
>>
>
> I never said here the this operator ""s should work with this: F"foo {5}=
=20
> bar"s... To be fair, I have been thinking this should work only if every=
=20
> single part is convertible to std::string. So the result is unambiguous, =
so=20
> it doesn't matter if it is fixed, unchangeable.
> And if you want a function call, do a function call, it will work.
> =20
>
>>
>> That's bad. A function call will be more versatile.
>>
>> You can't do that with a UDL; they can't take an extra template=20
>>>> parameter. `std::concat` can.
>>>>
>>>
>>> To do that, just use a function. We can have multiple syntaxes to do th=
e=20
>>> same thing.
>>> The closest example I can think of is:
>>> auto s =3D std::string("str");
>>> // is equivalent to
>>> auto s =3D "str"s;
>>>
>>>
>> No, it's not:
>>
>> auto s1 =3D std::string("str\0str");
>> auto s2 =3D "str\0str"s;
>>
>> In `s1` the constructor has to do `char_traits<char>::length` to compute=
=20
>> the number of characters in the string. That will terminate the string a=
t=20
>> the first NUL character. In the second case, the UDL gets the size from =
the=20
>> literal parameter directly.
>>
>> Things like this are why it is important to separate literal operations=
=20
>> from string interpolation. So that UDLs can do the job they exist to do=
=20
>> (literal synthesis) and string interpolation can do the job its meant to=
 do=20
>> (breaking down literals into sequences of values). And the aggregation c=
an=20
>> do the job its meant to do (take sequences of values and act on them).
>>
>
> String literals are broken now. This is not fixable by UDL currently. So=
=20
> all in all, we are doomed here.
>
If you write a function that need to take std::string_view for literal=20
> parts, let's do that, you don't need to force the literal to be a=20
> string_view to work, as they are implicitly convertible from const char[]=
&.=20
> The same with std::string.
> No, forget about that. Even that is not true (why?).
>

Because it would never be called. Basically, what you'd need is this=20
constructor:

template<size_t N>
string_view(const char s[N]);

But you already have this constructor:

string_view(const char *s);

An array decays into a pointer. And since the pointer constructor is not a=
=20
template, it is considered a better match than the array version. And=20
therefore, any ltieral you pass will go through the pointer version rather=
=20
than the array template.

And it should be noted that this has nothing to do with being a literal. If=
=20
you used a `const char[]` variable, it *still* would prefer the pointer=20
version due to array->pointer conversion. So this is not a case of "string=
=20
literals are broken now".

But there's no "fix" for this, since any array->pointer "fix" would be both=
=20
wildly incompatible with C and break tons and tons of code. So you can=20
either accept the language and work with what we have, or rail against it.

It's funny how the more I dig in C++, the more bulky it appears to be just=
=20
> because of these very small annoyances.
> =20
>
>>
>> It's a 3 step process; let's not interfere in that.
>> =20
>>
>>> We could have exatcly the situation with string interpolation:
>>> auto s =3D std::concat(F"{str1}{str2}{str3}");
>>> // would be equivalent to
>>> auto s =3D F"{str1}{str2}{str3}"s;
>>>
>>> I don't see why allowing UDL to work like that would decrease usability=
=20
>>> as we could always use regular functions.
>>>
>>
>> Because you can't do this:
>>
>> std::concat(F"some string {variable} other string"sv);
>>
>> Under my system, the UDL employed here allows you to decide how to=20
>> process each of the literal fragments. The UDL applies to the parts of t=
he=20
>> literal that are actually strings. So `concat` would get `string_view`s,=
=20
>> rather than `const char[X]` parameters.
>>
>> Under your system, the processing of the literal fragments is controlled=
=20
>> entirely by the system that computes the aggregation.
>>
>
> Let's sum up, string literals are broken today. So we should probably try=
=20
> to solve this big issue before trying to see how we can cripple=20
> string_interpolation in order to fit in current-ish C++.
>

I fail to see why applying a UDL to the literal fragments rather than the=
=20
interpolation aggregation operation should be considered "crippling" string=
=20
interpolation.

Whatever breakage you see in literals isn't standing in the way of string=
=20
interpolation. It's just standing in the way of string interpolation=20
working the way *you* want it to.

--=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/0e0876bb-7a44-45ff-ab9b-6443e78ea59c%40isocpp.or=
g.

------=_Part_5992_217892087.1518539749572
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Tuesday, February 13, 2018 at 4:50:00 AM UTC-5, floria.=
...@gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;mar=
gin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D=
"ltr">Le mardi 13 f=C3=A9vrier 2018 07:28:45 UTC+1, Nicol Bolas a =C3=A9cri=
t=C2=A0:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">On Monday,=
 February 12, 2018 at 4:08:37 PM UTC-5, <a>floria...@gmail.com</a> wrote:<b=
lockquote 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=A9v=
rier 2018 21:11:14 UTC+1, Nicol Bolas a =C3=A9crit=C2=A0:<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">On Monday, February 12, 2018 at 12:=
43:41 PM 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;padd=
ing-left:1ex"><div dir=3D"ltr">Le lundi 12 f=C3=A9vrier 2018 17:56:48 UTC+1=
, Nicol Bolas a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D=
"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><d=
iv dir=3D"ltr">On Monday, February 12, 2018 at 11:15:33 AM UTC-5, <a>floria=
....@gmail.com</a> wrote:</div></blockquote><blockquote class=3D"gmail_quote=
" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-le=
ft:1ex"><div dir=3D"ltr"><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> </div><blockquote class=3D"gmail_quote" style=3D"margin:0;ma=
rgin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"lt=
r"><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bo=
rder-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>With that =
in mind, the implementation 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::string_processing ).</div><div><br></div><div>And then, with=
 only c++17 metaprogramming capabilities, you could also use std::apply.<br=
></div></div></blockquote><div><br>You cannot `apply` things to operators. =
Not without creating a lambda function that gets called with it.<br></div><=
/div></blockquote><div>=C2=A0</div><div>Why not? You can get the address of=
 an operator, and this is a callable object.</div></div></blockquote><div><=
br>You can only get the address of a single overload of an operator. Rememb=
er: the whole idea is that you&#39;re dealing with a sequence of variables =
of different types. So the second parameter to the operator has to be of di=
fferent types for different invocations of the operator.<br></div></div></b=
lockquote><div><br></div><div>This is another quirk of C++ that should be f=
ixed.<br></div></div></blockquote><div><br>Which incidentally is yet anothe=
r proposal (lifting lambdas) that stalled.<br><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></div><blockquote class=3D"gma=
il_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pa=
dding-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D=
"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><d=
iv dir=3D"ltr"><div></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>The fact is, it&#39;s a <i>lot</i> easier in C++ as it curren=
tly stands to go from parameter pack of values to an object than it is to g=
o from an object to a parameter pack of values. I wish that were not the ca=
se, but so long as it is the case, parameter packs will remain the easier-t=
o-use option.<br></div></div></blockquote><div>=C2=A0</div><div>You have a =
point. <br></div><div><br></div><blockquote class=3D"gmail_quote" style=3D"=
margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><di=
v dir=3D"ltr"><div><br></div><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div d=
ir=3D"ltr"><div></div><div></div>UDL the aggregate 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 impossible to apply a UDL to the str=
ing fragments. And that&#39;s important if you do want to use template meta=
programming 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 would be.</div><div><div style=3D"b=
ackground-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><=
span style=3D"color:#000"> s </span><span style=3D"color:#660">=3D</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#080">&quot;something=
&quot;</span><span style=3D"color:#000">s</span><span style=3D"color:#660">=
;</span><span style=3D"color:#000"> </span><span style=3D"color:#800">// s =
is a string</span><span style=3D"color:#000"><br></span><span style=3D"colo=
r:#008">auto</span><span style=3D"color:#000"> sv </span><span style=3D"col=
or:#660">=3D</span><span style=3D"color:#000"> </span><span style=3D"color:=
#080">&quot;some other&quot;</span><span style=3D"color:#000">sv</span><spa=
n style=3D"color:#660">;</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#800">// s is a string view</span><span style=3D"color:#000"><b=
r></span></div></code></div>We are not interested in what is happening in t=
he middle. I don&#39;t why it should be different with string interpolation=
 (or whatever the name is).<br></div></div></blockquote><div><br>Because no=
t all of the &quot;literal&quot; is actually a literal anymore. That&#39;s =
the whole point of string interpolation: you&#39;re taking a literal and yo=
u&#39;re augmenting it with some non-literal data. Potentially <i>runtime</=
i> non-literal data. It isn&#39;t a literal anymore, so the UDL suffix can&=
#39;t apply to the aggregate. It can only apply to the individual literal f=
ragments of the string.<br></div></div></blockquote><div><br></div><div>Her=
e, I don&#39;t care if it&#39;s called a literal, or if we invent a new nam=
e for this concept that appeared to match the concept of literal when &quot=
;string interpolation&quot; was not a thing.</div><div>I&#39;m more interes=
ted in the final syntax as the end user will see it.</div><div><br></div><d=
iv>And I would prefer concatenate like this:</div><div><div style=3D"backgr=
ound-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:soli=
d;border-width:1px"><code><div><span style=3D"color:#008">auto</span><span =
style=3D"color:#000"> s </span><span style=3D"color:#660">=3D</span><span s=
tyle=3D"color:#000"> F</span><span style=3D"color:#080">&quot;{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></div></code></div></div=
><div>than this:</div><div><div style=3D"background-color:rgb(250,250,250);=
border-color:rgb(187,187,187);border-style:solid;border-width:1px"><code><d=
iv><span style=3D"color:#008">auto</span><span style=3D"color:#000"> s </sp=
an><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> std</sp=
an><span style=3D"color:#660">::</span><span style=3D"color:#000">concat</s=
pan><span style=3D"color:#660">(</span><span style=3D"color:#000">F</span><=
span style=3D"color:#080">&quot;{str1}{str2}{<wbr>str3}&quot;</span><span s=
tyle=3D"color:#660">);</span><span style=3D"color:#000"><br></span></div></=
code></div><br>The first one looks more natural in my opinion.<br></div></d=
iv></blockquote><div><br>It only looks more natural for the trivial cases. =
Consider what `std::concat` would look like. It creates an `ostringstream`,=
 applies it to each parameter, and moves its result out. Why pick `ostrings=
tream`? Why not allow the user to decide which kind of stream to use and th=
erefore which resulting string type to build?<br></div></div></blockquote><=
div><br></div><div>I never said this should work only with UDL. I just said=
 that I think it is more natural if UDL worked like that.</div><div>But I r=
eally think the user should keep control over what can be done with this sy=
ntax.</div><div>So I totally agree with you: users should be able to call t=
heir own functions with it.</div><div><br></div><div>And then, even conside=
ring F&quot;{str1}{str2}{str3}&quot;s for concatenating, I never mentionned=
 std::ostringstream, I just said converted into an efficient way of concate=
nating strings.</div><div>In that case, I just considered that when we use =
operator &quot;&quot;s, we want a std::string.<br></div></div></blockquote>=
<div><br>You say that the literal `s` means you want a `std::string`. But t=
hat&#39;s not enough information, because you now have to define how to <i>=
get</i> a `std::string` from values that aren&#39;t `std::string`. That&#39=
;s why you need more information than a mere literal can provide.<br><br>Th=
ere are many ways to get a std::string from an interpolated string. Your `o=
perator&quot;&quot;s` will only be doing one of them. That mechanism will b=
e <i>fixed</i>. Inflexible. Unchangeable.<br></div></div></blockquote><div>=
<br></div><div>I never said here the this operator &quot;&quot;s should wor=
k with this: F&quot;foo {5} bar&quot;s... To be fair, I have been thinking =
this should work only if every single part is convertible to std::string. S=
o the result is unambiguous, so it doesn&#39;t matter if it is fixed, uncha=
ngeable.</div><div>And if you want a function call, do a function call, it =
will work.<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex=
"><div dir=3D"ltr"><div><br>That&#39;s bad. A function call will be more ve=
rsatile.<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"l=
tr"><div></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"><di=
v>You can&#39;t do that with a UDL; they can&#39;t take an extra template p=
arameter. `std::concat` can.<br></div></div></blockquote><div><br></div><di=
v>To do that, just use a function. We can have multiple syntaxes to do the =
same thing.</div><div>The closest example I can think of is:</div><div><div=
 style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);b=
order-style:solid;border-width:1px"><code><div><span style=3D"color:#008">a=
uto</span><span style=3D"color:#000"> s </span><span style=3D"color:#660">=
=3D</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"=
>(</span><span style=3D"color:#080">&quot;str&quot;</span><span style=3D"co=
lor:#660">);</span><span style=3D"color:#000"><br></span><span style=3D"col=
or:#800">// is equivalent to</span><span style=3D"color:#000"><br></span><s=
pan style=3D"color:#008">auto</span><span style=3D"color:#000"> s </span><s=
pan style=3D"color:#660">=3D</span><span style=3D"color:#000"> </span><span=
 style=3D"color:#080">&quot;str&quot;</span><span style=3D"color:#000">s</s=
pan><span style=3D"color:#660">;</span><span style=3D"color:#000"><br></spa=
n></div></code></div></div><div><br></div></div></blockquote><div><br>No, i=
t&#39;s not:<br><br><div style=3D"background-color:rgb(250,250,250);border-=
color:rgb(187,187,187);border-style:solid;border-width:1px"><code><div><spa=
n style=3D"color:#008">auto</span><span style=3D"color:#000"> s1 </span><sp=
an style=3D"color:#660">=3D</span><span style=3D"color:#000"> std</span><sp=
an style=3D"color:#660">::</span><span style=3D"color:#008">string</span><s=
pan style=3D"color:#660">(</span><span style=3D"color:#080">&quot;str\0str&=
quot;</span><span style=3D"color:#660">);</span><span style=3D"color:#000">=
<br></span><span style=3D"color:#008">auto</span><span style=3D"color:#000"=
> s2 </span><span style=3D"color:#660">=3D</span><span style=3D"color:#000"=
> </span><span style=3D"color:#080">&quot;str\0str&quot;</span><span style=
=3D"color:#000">s</span><span style=3D"color:#660">;</span></div></code></d=
iv><br>In `s1` the constructor has to do `char_traits&lt;char&gt;::length` =
to compute the number of characters in the string. That will terminate the =
string at the first NUL character. In the second case, the UDL gets the siz=
e from the literal parameter directly.<br><br>Things like this are why it i=
s important to separate literal operations from string interpolation. So th=
at UDLs can do the job they exist to do (literal synthesis) and string inte=
rpolation can do the job its meant to do (breaking down literals into seque=
nces of values). And the aggregation can do the job its meant to do (take s=
equences of values and act on them).<br></div></div></blockquote><div><br><=
/div><div>String literals are broken now. This is not fixable by UDL curren=
tly. So all in all, we are doomed here.</div></div></blockquote><blockquote=
 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>If you write a func=
tion that need to take std::string_view for literal parts, let&#39;s do tha=
t, you don&#39;t need to force the literal to be a string_view to work, as =
they are implicitly convertible from const char[]&amp;. The same with std::=
string.</div><div>No, forget about that. Even that is not true (why?).</div=
></div></blockquote><div><br>Because it would never be called. Basically, w=
hat you&#39;d need is this constructor:<br><br><div style=3D"background-col=
or: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: sol=
id; border-width: 1px; overflow-wrap: break-word;" class=3D"prettyprint"><c=
ode class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">template</span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify">size_t N</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">&gt;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>string_view</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">(</span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">const</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">char</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 style=3D"color: #000;" class=3D"styled-by-prettify">N</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">]);</span></div></code></d=
iv><br>But you already have this constructor:<br><br><div style=3D"backgrou=
nd-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-styl=
e: solid; border-width: 1px; overflow-wrap: break-word;" class=3D"prettypri=
nt"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=
=3D"color: #000;" class=3D"styled-by-prettify">string_view</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">const</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">char</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">*</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></code></div><br>An array decays into a pointer. And since the point=
er constructor is not a template, it is considered a better match than the =
array version. And therefore, any ltieral you pass will go through the poin=
ter version rather than the array template.<br><br>And it should be noted t=
hat this has nothing to do with being a literal. If you used a `const char[=
]` variable, it <i>still</i> would prefer the pointer version due to array-=
&gt;pointer conversion. So this is not a case of &quot;string literals are =
broken now&quot;.<br><br>But there&#39;s no &quot;fix&quot; for this, since=
 any array-&gt;pointer &quot;fix&quot; would be both wildly incompatible wi=
th C and break tons and tons of code. So you can either accept the language=
 and work with what we have, or rail against it.<br><br></div><blockquote c=
lass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px=
 #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>It&#39;s funny how th=
e more I dig in C++, the more bulky it appears to be just because of these =
very small annoyances.<br></div><div>=C2=A0</div><blockquote class=3D"gmail=
_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padd=
ing-left:1ex"><div dir=3D"ltr"><div><br>It&#39;s a 3 step process; let&#39;=
s not interfere in that.<br>=C2=A0</div><blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:=
1ex"><div dir=3D"ltr"><div></div><div>We could have exatcly the situation w=
ith string interpolation:</div><div><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:#008">auto</span><span style=3D"color:#000=
"> s </span><span style=3D"color:#660">=3D</span><span style=3D"color:#000"=
> std</span><span style=3D"color:#660">::</span><span style=3D"color:#000">=
concat</span><span style=3D"color:#660">(</span><span style=3D"color:#000">=
F</span><span style=3D"color:#080">&quot;{str1}{str2}{<wbr>str3}&quot;</spa=
n><span style=3D"color:#660">);</span><span style=3D"color:#000"><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"> s </span><span style=3D"color:#660">=3D</span><span style=3D"=
color:#000"> F</span><span style=3D"color:#080">&quot;{str1}{str2}{str3}&qu=
ot;</span><span style=3D"color:#000">s</span><span style=3D"color:#660">;</=
span><span style=3D"color:#000"><br></span></div></code></div><br>I don&#39=
;t see why allowing UDL to work like that would decrease usability as we co=
uld always use regular functions.<br></div></div></blockquote><div><br>Beca=
use you can&#39;t do this:<br><br><div style=3D"background-color:rgb(250,25=
0,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">:=
:</span><span style=3D"color:#000">concat</span><span style=3D"color:#660">=
(</span><span style=3D"color:#000">F</span><span style=3D"color:#080">&quot=
;some string {variable} other string&quot;</span><span style=3D"color:#000"=
>sv</span><span style=3D"color:#660">);</span></div></code></div><br>Under =
my system, the UDL employed here allows you to decide how to process each o=
f the literal fragments. The UDL applies to the parts of the literal that a=
re actually strings. So `concat` would get `string_view`s, rather than `con=
st char[X]` parameters.<br><br>Under your system, the processing of the lit=
eral fragments is controlled entirely by the system that computes the aggre=
gation.</div></div></blockquote><div><br></div><div>Let&#39;s sum up, strin=
g literals are broken today. So we should probably try to solve this big is=
sue before trying to see how we can cripple string_interpolation in order t=
o fit in current-ish C++.<br></div></div></blockquote><div><br>I fail to se=
e why applying a UDL to the literal fragments rather than the interpolation=
 aggregation operation should be considered &quot;crippling&quot; string in=
terpolation.<br><br>Whatever breakage you see in literals isn&#39;t standin=
g in the way of string interpolation. It&#39;s just standing in the way of =
string interpolation working the way <i>you</i> want it to.<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/0e0876bb-7a44-45ff-ab9b-6443e78ea59c%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/0e0876bb-7a44-45ff-ab9b-6443e78ea59c=
%40isocpp.org</a>.<br />

------=_Part_5992_217892087.1518539749572--

------=_Part_5991_505544240.1518539749571--

.
