Topic: Determining lifetime invariants of function parameters


Author: Matthew Fioravante <fmatthew5876@gmail.com>
Date: Mon, 22 May 2017 10:19:51 -0700 (PDT)
Raw View
------=_Part_2840_1627786971.1495473591364
Content-Type: multipart/alternative;
 boundary="----=_Part_2841_546423242.1495473591365"

------=_Part_2841_546423242.1495473591365
Content-Type: text/plain; charset="UTF-8"

This sounds like something that's been discussed before.

Specifically what I'm concerned with is some way to determine whether or
not the parameter to a function call came from a constexpr object or not.
The reason why this information is useful is because anything constexpr
essentially is guaranteed to have "infinite" lifetime. The function itself
may or may not be constexpr, but if I know a parameter came from a
constexpr object I know I never have to worry about its lifetime.

One driving use case for this is logging. Suppose I have a printf() style
logger where the actual formatting and logging is done on another thread.

Logger log;
log.logf("x={}", x); //Infinite lifetime, never need to copy
char buf[] = "x={}";
log.logf(buf,x); //Local lifetime, must copy if the format string needs to
be accessed after logf() returns.



If the format string is a string literal (95% use case) then I don't need
to copy it. I can just maintain a pointer because I know that pointer will
never be invalid. If the format string is a run-time user string (5% use
case) then I don't know anything about its lifetime and must fallback to
copying.

The main problem here is that without providing additional information at
the call-site (different function, extra function args, different types,
user defined literals, etc..), there's no way the logf() can know anything
about the lifetime of the format string. We want to just say logf("Format
String", args...) and we want it to be fast. Requiring the user to remember
to do something at each and every logging call is a first class invitation
to bugs. Its especially frustrating since the compiler already knows this
information when it sees a string literal or any other constexpr object
passed in at the callsite.

I don't know whats the best solution here. Some options could be:

1. Add constexpr overloading

Then you'd write overloads like this:

//For run-time fmt strings
template <typename... Args>
void logf(string_view fmt, Args&&...);

//For compile-time fmt strings
template <size_t N, typename... Args>
void logf(constexpr const char (&fmt)[N], Args&&...);


2. Solve only this specific problem with a magic type like
std::string_literal<char,N>

There have been compile time static_string<char,N> like types discussed
before. This one would be like that except it has one extra special magic
property that it always overloads on string literals without any user
defined literal syntax specified. Since string literals are always
null-terminated, std::string_literal<char,N> should also always be assumed
null-terminated as well.

3. Add some runtime API to tell us something about the storage lifetime of
a pointer based on its address.

This would be some function like:

bool is_global(const void* p);

Would return true if p points to an object with global storage
(thread_local or not) that's always alive for the lifetime of the
application. Implementation wise, it would require knowing something about
the memory map of the process. I don't know if this is implementable on all
platforms. If not, it could be considered an optional "optimization" which
always returns false on unsupported platforms.

Option (1) seems very hard to get right and could potentially break
backwards compatibility. Particularly if templates start accepting
constexpr and non-constexpr overloads.

This is good enough use case that (2) is not completely crazy but still it
might be too specific when the problem is generic. People will balk at
having a magic type with magic treatment of string literals but
unfortunately there's no other way I know of to overload specifically on a
string_literal. User defined literals are a half solution. Having to say
"x={}"_ss or "x={}"_sl is something easy to forget, especially in my
example where forgetting the literal suffix will silently and automatically
call the slower string_view overload.

Option (3) seems to be the least intrusive way to do this. Now we're just
talking global and not constexpr, which opens up more use cases. The
trade-off is that you can't rely on this for lifetimes if its being called
before or after main().

How would you deal with this problem?

--
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 email 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/4bc7f035-4abb-44d1-8528-79db525b9daa%40isocpp.org.

------=_Part_2841_546423242.1495473591365
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">This sounds like something that&#39;s been discussed befor=
e.<div><br></div><div>Specifically what I&#39;m concerned with is some way =
to determine whether or not the parameter to a function call came from a co=
nstexpr object or not. The reason why this information is useful is because=
 anything constexpr essentially is guaranteed to have &quot;infinite&quot; =
lifetime. The function itself may or may not be constexpr, but if I know a =
parameter came from a constexpr object I know I never have to worry about i=
ts lifetime.</div><div><br></div><div>One driving use case for this is logg=
ing. Suppose I have a printf() style logger where the actual formatting and=
 logging is done on another thread.</div><div><br></div><div><div class=3D"=
prettyprint" style=3D"background-color: rgb(250, 250, 250); border-color: r=
gb(187, 187, 187); border-style: solid; border-width: 1px; word-wrap: break=
-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><font col=
or=3D"#660066"><span style=3D"color: #606;" class=3D"styled-by-prettify">Lo=
gger</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> log</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"><br>log</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">logf</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #080;" cl=
ass=3D"styled-by-prettify">&quot;x=3D{}&quot;</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> x</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">);</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-prettify"=
>//Infinite lifetime, never need to copy</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">char</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> buf</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">[]</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #080;" class=3D"styled-by-prettify">&quot;x=3D{}&quot;</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"><br>log</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify">logf</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify">buf</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify">x</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>);</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #800;" class=3D"styled-by-prettify">//Local lifetime=
, must copy if the format string needs to be accessed after logf() returns.=
</span></font></div></code></div><br><br></div><div><br></div><div>If the f=
ormat string is a string literal (95% use case) then I don&#39;t need to co=
py it. I can just maintain a pointer because I know that pointer will never=
 be invalid. If the format string is a run-time user string (5% use case) t=
hen I don&#39;t know anything about its lifetime and must fallback to copyi=
ng.</div><div><br></div><div>The main problem here is that without providin=
g additional information at the call-site (different function, extra functi=
on args, different types, user defined literals, etc..), there&#39;s no way=
 the logf() can know anything about the lifetime of the format string. We w=
ant to just say logf(&quot;Format String&quot;, args...) and we want it to =
be fast. Requiring the user to remember to do something at each and every l=
ogging call is a first class invitation to bugs. Its especially frustrating=
 since the compiler already knows this information when it sees a string li=
teral or any other constexpr object passed in at the callsite.</div><div><b=
r></div><div>I don&#39;t know whats the best solution here. Some options co=
uld be:</div><div><br></div><div>1. Add constexpr overloading</div><div><br=
></div><div>Then you&#39;d write overloads like this:</div><div><br></div><=
div><div class=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250=
); border-color: rgb(187, 187, 187); border-style: solid; border-width: 1px=
; word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"subpret=
typrint"><span style=3D"color: #800;" class=3D"styled-by-prettify">//For ru=
n-time fmt strings</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify=
">template</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
 </span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</spa=
n><span style=3D"color: #008;" class=3D"styled-by-prettify">typename</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">...</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: #606;" class=3D"styled-by-prettify">Args</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">&gt;</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">void</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> logf</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">(</span><font color=3D"#000088"><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify">string_view</span></font><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: #000;" class=3D=
"styled-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-b=
y-prettify">Args</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">&amp;&amp;...);</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br><br></span><span style=3D"color: #800;" class=3D"styled-by-p=
rettify">//For compile-time fmt strings</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">template</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">&lt;</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify">size_t N</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">typename</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">...</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #606;" class=3D"styled-by-prettify">Args</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">&gt;</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" =
class=3D"styled-by-prettify">void</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> logf</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">(</span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">constexpr</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
const</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">char</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(&amp;</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: #000;" c=
lass=3D"styled-by-prettify">N</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: #606;" class=3D"styled-by-prettify=
">Args</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&amp=
;&amp;...);</span></div></code></div><br><br></div><div>2. Solve only this =
specific problem with a magic type like std::string_literal&lt;char,N&gt;</=
div><div><br></div><div>There have been compile time static_string&lt;char,=
N&gt; like types discussed before. This one would be like that except it ha=
s one extra special magic property that it always overloads on string liter=
als without any user defined literal syntax specified. Since string literal=
s are always null-terminated, std::string_literal&lt;char,N&gt; should also=
 always be assumed null-terminated as well.</div><div><br></div><div>3. Add=
 some runtime API to tell us something about the storage lifetime of a poin=
ter based on its address.</div><div><br></div><div>This would be some funct=
ion like:</div><div><br></div><div><div class=3D"prettyprint" style=3D"back=
ground-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-=
style: solid; border-width: 1px; word-wrap: break-word;"><code class=3D"pre=
ttyprint"><div class=3D"subprettyprint"><font color=3D"#660066"><span style=
=3D"color: #008;" class=3D"styled-by-prettify">bool</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> is_global</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">const</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">void</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">*</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> p</span><span style=3D"color: #660;" class=3D"styled-by-prettify">);</s=
pan></font></div></code></div><br>Would return true if p points to an objec=
t with global storage (thread_local or not) that&#39;s always alive for the=
 lifetime of the application. Implementation wise, it would require knowing=
 something about the memory map of the process. I don&#39;t know if this is=
 implementable on all platforms. If not, it could be considered an optional=
 &quot;optimization&quot; which always returns false on unsupported platfor=
ms.</div><div><br></div><div>Option (1) seems very hard to get right and co=
uld potentially break backwards compatibility. Particularly if templates st=
art accepting constexpr and non-constexpr overloads.=C2=A0</div><div><br></=
div><div>This is good enough use case that (2) is not completely crazy but =
still it might be too specific when the problem is generic. People will bal=
k at having a magic type with magic treatment of string literals but unfort=
unately there&#39;s no other way I know of to overload specifically on a st=
ring_literal. User defined literals are a half solution. Having to say &quo=
t;x=3D{}&quot;_ss or &quot;x=3D{}&quot;_sl is something easy to forget, esp=
ecially in my example where forgetting the literal suffix will silently and=
 automatically call the slower string_view overload.</div><div><br></div><d=
iv>Option (3) seems to be the least intrusive way to do this. Now we&#39;re=
 just talking global and not constexpr, which opens up more use cases. The =
trade-off is that you can&#39;t rely on this for lifetimes if its being cal=
led before or after main().</div><div><br></div><div>How would you deal wit=
h this problem?</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/4bc7f035-4abb-44d1-8528-79db525b9daa%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/4bc7f035-4abb-44d1-8528-79db525b9daa=
%40isocpp.org</a>.<br />

------=_Part_2841_546423242.1495473591365--

------=_Part_2840_1627786971.1495473591364--

.


Author: Thiago Macieira <thiago@macieira.org>
Date: Mon, 22 May 2017 10:56:51 -0700
Raw View
On Monday, 22 May 2017 10:19:51 PDT Matthew Fioravante wrote:
> Specifically what I'm concerned with is some way to determine whether or
> not the parameter to a function call came from a constexpr object or not.
> The reason why this information is useful is because anything constexpr
> essentially is guaranteed to have "infinite" lifetime.

By the way, "infinite" is a lot shorter when plugins are involved. The moment
that you can unload code and constants, the lifetime of anything is finite.

--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
   Software Architect - Intel Open Source Technology Center

--
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 email 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/2028135.l9HhMGYvqA%40tjmaciei-mobl1.

.


Author: Tony V E <tvaneerd@gmail.com>
Date: Mon, 22 May 2017 14:02:07 -0400
Raw View
<html><head></head><body lang=3D"en-US" style=3D"background-color: rgb(255,=
 255, 255); line-height: initial;">                                        =
                                              <div style=3D"width: 100%; fo=
nt-size: initial; font-family: Calibri, 'Slate Pro', sans-serif, sans-serif=
; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, =
255, 255);"><br></div><span style=3D"font-family: monospace; background-col=
or: rgb(250, 250, 250); color: rgb(0, 0, 136);">bool</span><span style=3D"f=
ont-family: monospace; background-color: rgb(250, 250, 250);">&nbsp;is_glob=
al</span><span style=3D"font-family: monospace; background-color: rgb(250, =
250, 250); color: rgb(102, 102, 0);">(</span><span style=3D"font-family: mo=
nospace; background-color: rgb(250, 250, 250); color: rgb(0, 0, 136);">cons=
t</span><span style=3D"font-family: monospace; background-color: rgb(250, 2=
50, 250);">&nbsp;</span><span style=3D"font-family: monospace; background-c=
olor: rgb(250, 250, 250); color: rgb(0, 0, 136);">void</span><span style=3D=
"font-family: monospace; background-color: rgb(250, 250, 250); color: rgb(1=
02, 102, 0);">*</span><span style=3D"font-family: monospace; background-col=
or: rgb(250, 250, 250);">&nbsp;p</span><span style=3D"font-family: monospac=
e; background-color: rgb(250, 250, 250); color: rgb(102, 102, 0);">);</span=
><div style=3D"width: 100%; font-size: initial; font-family: Calibri, 'Slat=
e Pro', sans-serif, sans-serif; color: rgb(31, 73, 125); text-align: initia=
l; background-color: rgb(255, 255, 255);"><br></div><div style=3D"width: 10=
0%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif, sans=
-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb=
(255, 255, 255);"><br></div><div style=3D"width: 100%; font-size: initial; =
font-family: Calibri, 'Slate Pro', sans-serif, sans-serif; color: rgb(31, 7=
3, 125); text-align: initial; background-color: rgb(255, 255, 255);"><br></=
div><div style=3D"width: 100%; font-size: initial; font-family: Calibri, 'S=
late Pro', sans-serif, sans-serif; color: rgb(31, 73, 125); text-align: ini=
tial; background-color: rgb(255, 255, 255);"><br></div><div style=3D"width:=
 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif, s=
ans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: =
rgb(255, 255, 255);">Is not what you want. You also need it to be immutable=
 </div><div style=3D"width: 100%; font-size: initial; font-family: Calibri,=
 'Slate Pro', sans-serif, sans-serif; color: rgb(31, 73, 125); text-align: =
initial; background-color: rgb(255, 255, 255);"><br></div><div style=3D"wid=
th: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif=
, sans-serif; color: rgb(31, 73, 125); text-align: initial; background-colo=
r: rgb(255, 255, 255);">is_immutable(const void *p, int len =3D -1); // -1 =
means until null terminator</div><div style=3D"width: 100%; font-size: init=
ial; font-family: Calibri, 'Slate Pro', sans-serif, sans-serif; color: rgb(=
31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);"><=
br></div><div style=3D"width: 100%; font-size: initial; font-family: Calibr=
i, 'Slate Pro', sans-serif, sans-serif; color: rgb(31, 73, 125); text-align=
: initial; background-color: rgb(255, 255, 255);"><br></div><div style=3D"w=
idth: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-ser=
if, sans-serif; color: rgb(31, 73, 125); text-align: initial; background-co=
lor: rgb(255, 255, 255);"><br></div><div style=3D"width: 100%; font-size: i=
nitial; font-family: Calibri, 'Slate Pro', sans-serif, sans-serif; color: r=
gb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);=
"><br></div>                                                               =
                                                                      <div =
style=3D"width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro'=
, sans-serif, sans-serif; color: rgb(31, 73, 125); text-align: initial; bac=
kground-color: rgb(255, 255, 255);"><br style=3D"display:initial"></div>   =
                                                                           =
                                                                           =
                                          <div style=3D"font-size: initial;=
 font-family: Calibri, 'Slate Pro', sans-serif, sans-serif; color: rgb(31, =
73, 125); text-align: initial; background-color: rgb(255, 255, 255);">Sent&=
nbsp;from&nbsp;my&nbsp;BlackBerry&nbsp;portable&nbsp;Babbage&nbsp;Device</d=
iv>                                                                        =
                                                                           =
                               <table width=3D"100%" style=3D"background-co=
lor:white;border-spacing:0px;"> <tbody><tr><td colspan=3D"2" style=3D"font-=
size: initial; text-align: initial; background-color: rgb(255, 255, 255);">=
                           <div style=3D"border-style: solid none none; bor=
der-top-color: rgb(181, 196, 223); border-top-width: 1pt; padding: 3pt 0in =
0in; font-family: Tahoma, 'BB Alpha Sans', 'Slate Pro'; font-size: 10pt;"> =
 <div><b>From: </b>Matthew Fioravante</div><div><b>Sent: </b>Monday, May 22=
, 2017 1:19 PM</div><div><b>To: </b>ISO C++ Standard - Future Proposals</di=
v><div><b>Reply To: </b>std-proposals@isocpp.org</div><div><b>Subject: </b>=
[std-proposals] Determining lifetime invariants of function parameters</div=
></div></td></tr></tbody></table><div style=3D"border-style: solid none non=
e; border-top-color: rgb(186, 188, 209); border-top-width: 1pt; font-size: =
initial; text-align: initial; background-color: rgb(255, 255, 255);"></div>=
<br><div id=3D"_originalContent" style=3D""><div dir=3D"ltr">This sounds li=
ke something that's been discussed before.<div><br></div><div>Specifically =
what I'm concerned with is some way to determine whether or not the paramet=
er to a function call came from a constexpr object or not. The reason why t=
his information is useful is because anything constexpr essentially is guar=
anteed to have "infinite" lifetime. The function itself may or may not be c=
onstexpr, but if I know a parameter came from a constexpr object I know I n=
ever have to worry about its lifetime.</div><div><br></div><div>One driving=
 use case for this is logging. Suppose I have a printf() style logger where=
 the actual formatting and logging is done on another thread.</div><div><br=
></div><div><div class=3D"prettyprint" style=3D"background-color: rgb(250, =
250, 250); border-color: rgb(187, 187, 187); border-style: solid; border-wi=
dth: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D=
"subprettyprint"><font color=3D"#660066"><span style=3D"color: #606;" class=
=3D"styled-by-prettify">Logger</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> log</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"><br>log</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">.</span><span style=3D"color: #000;" class=3D"styled-by-prettify">logf</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span=
 style=3D"color: #080;" class=3D"styled-by-prettify">"x=3D{}"</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> x</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">);</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"sty=
led-by-prettify">//Infinite lifetime, never need to copy</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">char</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> buf</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">[]</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> </span><span style=3D"color: #080;" class=3D"styled-by-prettify">"x=
=3D{}"</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>log</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">.</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify">logf</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify">buf</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">x</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">);</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #800;" class=3D"styled-by-prettify">//Local=
 lifetime, must copy if the format string needs to be accessed after logf()=
 returns.</span></font></div></code></div><br><br></div><div><br></div><div=
>If the format string is a string literal (95% use case) then I don't need =
to copy it. I can just maintain a pointer because I know that pointer will =
never be invalid. If the format string is a run-time user string (5% use ca=
se) then I don't know anything about its lifetime and must fallback to copy=
ing.</div><div><br></div><div>The main problem here is that without providi=
ng additional information at the call-site (different function, extra funct=
ion args, different types, user defined literals, etc..), there's no way th=
e logf() can know anything about the lifetime of the format string. We want=
 to just say logf("Format String", args...) and we want it to be fast. Requ=
iring the user to remember to do something at each and every logging call i=
s a first class invitation to bugs. Its especially frustrating since the co=
mpiler already knows this information when it sees a string literal or any =
other constexpr object passed in at the callsite.</div><div><br></div><div>=
I don't know whats the best solution here. Some options could be:</div><div=
><br></div><div>1. Add constexpr overloading</div><div><br></div><div>Then =
you'd write overloads like this:</div><div><br></div><div><div class=3D"pre=
ttyprint" style=3D"background-color: rgb(250, 250, 250); border-color: rgb(=
187, 187, 187); border-style: solid; border-width: 1px; word-wrap: break-wo=
rd;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=
=3D"color: #800;" class=3D"styled-by-prettify">//For run-time fmt strings</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><=
span style=3D"color: #008;" class=3D"styled-by-prettify">template</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">typename</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">...</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" class=
=3D"styled-by-prettify">Args</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">&gt;</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br></span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">void</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
 logf</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</sp=
an><font color=3D"#000088"><span style=3D"color: #000;" class=3D"styled-by-=
prettify">string_view</span></font><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> fmt</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">Args</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">&amp;&amp;..=
..);</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br=
></span><span style=3D"color: #800;" class=3D"styled-by-prettify">//For com=
pile-time fmt strings</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br></span><span style=3D"color: #008;" class=3D"styled-by-prett=
ify">template</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </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</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"=
color: #008;" class=3D"styled-by-prettify">typename</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">...</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" clas=
s=3D"styled-by-prettify">Args</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">&gt;</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"><br></span><span style=3D"color: #008;" class=3D"styled-by-pre=
ttify">void</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> logf</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</s=
pan><span style=3D"color: #008;" class=3D"styled-by-prettify">constexpr</sp=
an><span style=3D"color: #000;" 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"styled-by-prettify"> </span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">char</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(&amp;</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: #000;" class=3D"styled-by-prett=
ify">N</span><span style=3D"color: #660;" class=3D"styled-by-prettify">],</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #606;" class=3D"styled-by-prettify">Args</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">&amp;&amp;...);</span></div=
></code></div><br><br></div><div>2. Solve only this specific problem with a=
 magic type like std::string_literal&lt;char,N&gt;</div><div><br></div><div=
>There have been compile time static_string&lt;char,N&gt; like types discus=
sed before. This one would be like that except it has one extra special mag=
ic property that it always overloads on string literals without any user de=
fined literal syntax specified. Since string literals are always null-termi=
nated, std::string_literal&lt;char,N&gt; should also always be assumed null=
-terminated as well.</div><div><br></div><div>3. Add some runtime API to te=
ll us something about the storage lifetime of a pointer based on its addres=
s.</div><div><br></div><div>This would be some function like:</div><div><br=
></div><div><div class=3D"prettyprint" style=3D"background-color: rgb(250, =
250, 250); border-color: rgb(187, 187, 187); border-style: solid; border-wi=
dth: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D=
"subprettyprint"><font color=3D"#660066"><span style=3D"color: #008;" class=
=3D"styled-by-prettify">bool</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> is_global</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">(</span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">const</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">void<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">*</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> p</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">);</span></font></div></code=
></div><br>Would return true if p points to an object with global storage (=
thread_local or not) that's always alive for the lifetime of the applicatio=
n. Implementation wise, it would require knowing something about the memory=
 map of the process. I don't know if this is implementable on all platforms=
.. If not, it could be considered an optional "optimization" which always re=
turns false on unsupported platforms.</div><div><br></div><div>Option (1) s=
eems very hard to get right and could potentially break backwards compatibi=
lity. Particularly if templates start accepting constexpr and non-constexpr=
 overloads.&nbsp;</div><div><br></div><div>This is good enough use case tha=
t (2) is not completely crazy but still it might be too specific when the p=
roblem is generic. People will balk at having a magic type with magic treat=
ment of string literals but unfortunately there's no other way I know of to=
 overload specifically on a string_literal. User defined literals are a hal=
f solution. Having to say "x=3D{}"_ss or "x=3D{}"_sl is something easy to f=
orget, especially in my example where forgetting the literal suffix will si=
lently and automatically call the slower string_view overload.</div><div><b=
r></div><div>Option (3) seems to be the least intrusive way to do this. Now=
 we're just talking global and not constexpr, which opens up more use cases=
.. The trade-off is that you can't rely on this for lifetimes if its being c=
alled before or after main().</div><div><br></div><div>How would you deal w=
ith this problem?</div></div>

<p></p>

-- <br>
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" 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/4bc7f035-4abb-44d1-8528-79db525b9daa%=
40isocpp.org?utm_medium=3Demail&amp;utm_source=3Dfooter">https://groups.goo=
gle.com/a/isocpp.org/d/msgid/std-proposals/4bc7f035-4abb-44d1-8528-79db525b=
9daa%40isocpp.org</a>.<br>
<br><!--end of _originalContent --></div></body></html>

<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/20170522180207.5115986.78513.30264%40=
gmail.com?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.com=
/a/isocpp.org/d/msgid/std-proposals/20170522180207.5115986.78513.30264%40gm=
ail.com</a>.<br />

.