Topic: constexpr function arguments
Author: Andrey Semashev <andrey.semashev@gmail.com>
Date: Sun, 12 Apr 2015 13:33:09 +0300
Raw View
Hi,
I wonder if constexpr function arguments would be a useful addition to the
standard. Consider this part of std::atomic interface:
template< typename T >
void atomic<T>::store(T val, memory_order order)
{
switch (order)
{
// implementations with different memory ordering guarantees
}
}
The function itself is not constexpr because the implementation has a runtime
side effect. However the memory order argument is always constant in normal
uses and the implementation could have had benefitted from knowing this
constant at compile time. The current standard does not offer means for that,
so you're out of luck if the compiler is not smart enough to propagate this
constexpr hint behind the scenes. For the most part with compilers I have
experience with (gcc, icl, msvc) this only works when the compiler is able to
inline the function call.
BTW, if anyone wonders if compiler intrinsics help here, no they don't. With
the code similar to this:
template< typename T >
void atomic<T>::store(T val, memory_order order)
{
__atomic_store_n(&m_value, val, order);
}
gcc and icl simply fall back to memory_order_seq_cst regardless of the
specified order if they cannot inline the function. This always happens in
debug, for instance.
What I'm thinking is if we could require some argument to be constexpr and
pass that 'compile-timeness' hint to the function body, the implementation
could optimize better. For example:
template< typename T >
void atomic<T>::store(T val, constexpr memory_order order)
{
switch (order) // order is always constexpr
{
// implementations with different memory ordering guarantees
}
}
In this case the switch/case would always be optimized to a single case. And
the intrinsic-based version would also work as intended. Also, if we have a
non-constexpr overload of this function we would also support calling with a
runtime value of the memory order (not that it would be of much use though).
I understand this would have consequences on the ABI because constexpr
arguments essentiall require to duplicate the function body for each constant
argument value. It's not a big problem though because we already do that for
non-type template parameters.
Opinions?
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Alexander Marinov <sasho648@mail.bg>
Date: Sun, 12 Apr 2015 05:09:29 -0700 (PDT)
Raw View
------=_Part_2963_466898420.1428840569569
Content-Type: multipart/alternative;
boundary="----=_Part_2964_1992542773.1428840569570"
------=_Part_2964_1992542773.1428840569570
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
I already sketched the details of this idea. You can read it here=20
<https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/RTss7Uy=
lzgQ>.=20
Only someone needs to write a proposal and/or implement it as a demo in=20
some open-source compiler (GCC or Clang).
=D0=BD=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F, 12 =D0=B0=D0=BF=D1=80=D0=B8=D0=BB 201=
5 =D0=B3., 13:33:17 UTC+3, Andrey Semashev =D0=BD=D0=B0=D0=BF=D0=B8=D1=81=
=D0=B0:
>
> Hi,=20
>
> I wonder if constexpr function arguments would be a useful addition to th=
e=20
> standard. Consider this part of std::atomic interface:=20
>
> template< typename T >=20
> void atomic<T>::store(T val, memory_order order)=20
> {=20
> switch (order)=20
> {=20
> // implementations with different memory ordering guarantees=20
> }=20
> }=20
>
> The function itself is not constexpr because the implementation has a=20
> runtime=20
> side effect. However the memory order argument is always constant in=20
> normal=20
> uses and the implementation could have had benefitted from knowing this=
=20
> constant at compile time. The current standard does not offer means for=
=20
> that,=20
> so you're out of luck if the compiler is not smart enough to propagate=20
> this=20
> constexpr hint behind the scenes. For the most part with compilers I have=
=20
> experience with (gcc, icl, msvc) this only works when the compiler is abl=
e=20
> to=20
> inline the function call.=20
>
> BTW, if anyone wonders if compiler intrinsics help here, no they don't.=
=20
> With=20
> the code similar to this:=20
>
> template< typename T >=20
> void atomic<T>::store(T val, memory_order order)=20
> {=20
> __atomic_store_n(&m_value, val, order);=20
> }=20
>
> gcc and icl simply fall back to memory_order_seq_cst regardless of the=20
> specified order if they cannot inline the function. This always happens i=
n=20
> debug, for instance.=20
>
> What I'm thinking is if we could require some argument to be constexpr an=
d=20
> pass that 'compile-timeness' hint to the function body, the implementatio=
n=20
> could optimize better. For example:=20
>
> template< typename T >=20
> void atomic<T>::store(T val, constexpr memory_order order)=20
> {=20
> switch (order) // order is always constexpr=20
> {=20
> // implementations with different memory ordering guarantees=20
> }=20
> }=20
>
> In this case the switch/case would always be optimized to a single case.=
=20
> And=20
> the intrinsic-based version would also work as intended. Also, if we have=
=20
> a=20
> non-constexpr overload of this function we would also support calling wit=
h=20
> a=20
> runtime value of the memory order (not that it would be of much use=20
> though).=20
>
> I understand this would have consequences on the ABI because constexpr=20
> arguments essentiall require to duplicate the function body for each=20
> constant=20
> argument value. It's not a big problem though because we already do that=
=20
> for=20
> non-type template parameters.=20
>
> Opinions?=20
>
>
--=20
---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_2964_1992542773.1428840569570
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I already sketched the details of this idea. You can read =
it <a href=3D"https://groups.google.com/a/isocpp.org/forum/#!topic/std-prop=
osals/RTss7UylzgQ">here</a>. Only someone needs to write a proposal and/or =
implement it as a demo in some open-source compiler (GCC or Clang).<br><br>=
=D0=BD=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F, 12 =D0=B0=D0=BF=D1=80=D0=B8=D0=BB 201=
5 =D0=B3., 13:33:17 UTC+3, Andrey Semashev =D0=BD=D0=B0=D0=BF=D0=B8=D1=81=
=D0=B0:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.=
8ex;border-left: 1px #ccc solid;padding-left: 1ex;">Hi,
<br>
<br>I wonder if constexpr function arguments would be a useful addition to =
the=20
<br>standard. Consider this part of std::atomic interface:
<br>
<br> template< typename T >
<br> void atomic<T>::store(T val, memory_order order)
<br> {
<br> switch (order)
<br> {
<br> // implementations with different memory ordering =
guarantees
<br> }
<br> }
<br>
<br>The function itself is not constexpr because the implementation has a r=
untime=20
<br>side effect. However the memory order argument is always constant in no=
rmal=20
<br>uses and the implementation could have had benefitted from knowing this=
=20
<br>constant at compile time. The current standard does not offer means for=
that,=20
<br>so you're out of luck if the compiler is not smart enough to propagate =
this=20
<br>constexpr hint behind the scenes. For the most part with compilers I ha=
ve=20
<br>experience with (gcc, icl, msvc) this only works when the compiler is a=
ble to=20
<br>inline the function call.
<br>
<br>BTW, if anyone wonders if compiler intrinsics help here, no they don't.=
With=20
<br>the code similar to this:
<br>
<br> template< typename T >
<br> void atomic<T>::store(T val, memory_order order)
<br> {
<br> __atomic_store_n(&m_value, val, order);
<br> }
<br>
<br>gcc and icl simply fall back to memory_order_seq_cst regardless of the=
=20
<br>specified order if they cannot inline the function. This always happens=
in=20
<br>debug, for instance.
<br>
<br>What I'm thinking is if we could require some argument to be constexpr =
and=20
<br>pass that 'compile-timeness' hint to the function body, the implementat=
ion=20
<br>could optimize better. For example:
<br>
<br> template< typename T >
<br> void atomic<T>::store(T val, constexpr memory_order order)
<br> {
<br> switch (order) // order is always constexpr
<br> {
<br> // implementations with different memory ordering =
guarantees
<br> }
<br> }
<br>
<br>In this case the switch/case would always be optimized to a single case=
.. And=20
<br>the intrinsic-based version would also work as intended. Also, if we ha=
ve a=20
<br>non-constexpr overload of this function we would also support calling w=
ith a=20
<br>runtime value of the memory order (not that it would be of much use tho=
ugh).
<br>
<br>I understand this would have consequences on the ABI because constexpr=
=20
<br>arguments essentiall require to duplicate the function body for each co=
nstant=20
<br>argument value. It's not a big problem though because we already do tha=
t for=20
<br>non-type template parameters.
<br>
<br>Opinions?
<br>
<br></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2964_1992542773.1428840569570--
------=_Part_2963_466898420.1428840569569--
.
Author: Andrey Semashev <andrey.semashev@gmail.com>
Date: Sun, 12 Apr 2015 15:29:15 +0300
Raw View
On Sunday 12 April 2015 05:09:29 Alexander Marinov wrote:
> I already sketched the details of this idea. You can read it here
> <https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/RTss7=
Uyl
> zgQ>. Only someone needs to write a proposal and/or implement it as a dem=
o
> in some open-source compiler (GCC or Clang).
No, I don't think your proposal is related to my idea. I'm not trying to ma=
ke=20
a function constexpr, I'm trying to propagate compile-time nature of some o=
f=20
its arguments to its body, which is executed in run time.
(offtopic: And I do think that inline and constexpr are different propertie=
s=20
of the code, even though they are somewhat related on the implementation si=
de;=20
I do not think they should be mixed together in a single keyword.)
> =D0=BD=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F, 12 =D0=B0=D0=BF=D1=80=D0=B8=D0=BB 2=
015 =D0=B3., 13:33:17 UTC+3, Andrey Semashev =D0=BD=D0=B0=D0=BF=D0=B8=D1=81=
=D0=B0:
> > Hi,
> >=20
> > I wonder if constexpr function arguments would be a useful addition to =
the
> >=20
> > standard. Consider this part of std::atomic interface:
> > template< typename T >
> > void atomic<T>::store(T val, memory_order order)
> > {
> > =20
> > switch (order)
> > {
> > =20
> > // implementations with different memory ordering guarantees
> > =20
> > }
> > =20
> > }
> >=20
> > The function itself is not constexpr because the implementation has a
> > runtime
> > side effect. However the memory order argument is always constant in
> > normal
> > uses and the implementation could have had benefitted from knowing this
> > constant at compile time. The current standard does not offer means for
> > that,
> > so you're out of luck if the compiler is not smart enough to propagate
> > this
> > constexpr hint behind the scenes. For the most part with compilers I ha=
ve
> > experience with (gcc, icl, msvc) this only works when the compiler is a=
ble
> > to
> > inline the function call.
> >=20
> > BTW, if anyone wonders if compiler intrinsics help here, no they don't.
> > With
> >=20
> > the code similar to this:
> > template< typename T >
> > void atomic<T>::store(T val, memory_order order)
> > {
> > =20
> > __atomic_store_n(&m_value, val, order);
> > =20
> > }
> >=20
> > gcc and icl simply fall back to memory_order_seq_cst regardless of the
> > specified order if they cannot inline the function. This always happens=
in
> > debug, for instance.
> >=20
> > What I'm thinking is if we could require some argument to be constexpr =
and
> > pass that 'compile-timeness' hint to the function body, the implementat=
ion
> >=20
> > could optimize better. For example:
> > template< typename T >
> > void atomic<T>::store(T val, constexpr memory_order order)
> > {
> > =20
> > switch (order) // order is always constexpr
> > {
> > =20
> > // implementations with different memory ordering guarantees
> > =20
> > }
> > =20
> > }
> >=20
> > In this case the switch/case would always be optimized to a single case=
..
> > And
> > the intrinsic-based version would also work as intended. Also, if we ha=
ve
> > a
> > non-constexpr overload of this function we would also support calling w=
ith
> > a
> > runtime value of the memory order (not that it would be of much use
> > though).
> >=20
> > I understand this would have consequences on the ABI because constexpr
> > arguments essentiall require to duplicate the function body for each
> > constant
> > argument value. It's not a big problem though because we already do tha=
t
> > for
> > non-type template parameters.
> >=20
> > Opinions?
--=20
---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Alexander Marinov <sasho648@mail.bg>
Date: Sun, 12 Apr 2015 06:13:35 -0700 (PDT)
Raw View
------=_Part_223_1997393265.1428844415939
Content-Type: multipart/alternative;
boundary="----=_Part_224_724234951.1428844415939"
------=_Part_224_724234951.1428844415939
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
You read my proposal - it does the same thing you want even if you don't=20
fully understand it.
Actually 'constexpr' is a useless keyword - it adds nothing to 'inline'=20
functions which most compilers already optimize out and evaluate at=20
compile-time if possible. Much better will be the properties to 'constexpr'=
=20
to be automatically added to each inline function. And what are they=20
actually?
An 'constexpr' function may be evaluated at compile-time (so do 'inline').
An 'constexpr' function may be used at a constant-expression and if so -=20
it's required to be evaluated at compile-time.
Actually the second line is the so 'BIG' difference between those two but I=
=20
think that it can be implicitly applied to all 'inline' functions without=
=20
any issues (performance or whatever).
The part which fulfill your idea is 'inline' variables which are guaranteed=
=20
to be evaluated at run-time (as template parameters) and more specially=20
'inline' function parameters (which imply that the function they=20
declare/define is 'inline' because templates can't be defined at different=
=20
TU).
So your example will look like this by using my construct:
template< typename T >=20
void atomic<T>::store(T val, inline memory_order order)=20
{=20
switch (order) // order is always constexpr=20
{=20
// implementations with different memory ordering guarantees=20
}=20
}
With the exact same semantics you want. Function parameter 'order' will=20
accept only constant-expressions and it will be evaluated at compile-time.=
=20
Actually those semantics are possible now too but have different=20
syntax(etc. by using template parameters):
template< typename T, memory_order order >=20
void atomic<T>::store(T val)=20
{=20
switch (order) // order is always constexpr=20
{=20
// implementations with different memory ordering guarantees=20
}=20
}
=D0=BD=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F, 12 =D0=B0=D0=BF=D1=80=D0=B8=D0=BB 201=
5 =D0=B3., 15:29:21 UTC+3, Andrey Semashev =D0=BD=D0=B0=D0=BF=D0=B8=D1=81=
=D0=B0:
>
> On Sunday 12 April 2015 05:09:29 Alexander Marinov wrote:=20
> > I already sketched the details of this idea. You can read it here=20
> > <
> https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/RTss7U=
yl=20
> > zgQ>. Only someone needs to write a proposal and/or implement it as a=
=20
> demo=20
> > in some open-source compiler (GCC or Clang).=20
>
> No, I don't think your proposal is related to my idea. I'm not trying to=
=20
> make=20
> a function constexpr, I'm trying to propagate compile-time nature of some=
=20
> of=20
> its arguments to its body, which is executed in run time.=20
>
> (offtopic: And I do think that inline and constexpr are different=20
> properties=20
> of the code, even though they are somewhat related on the implementation=
=20
> side;=20
> I do not think they should be mixed together in a single keyword.)=20
>
> > =D0=BD=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F, 12 =D0=B0=D0=BF=D1=80=D0=B8=D0=BB=
2015 =D0=B3., 13:33:17 UTC+3, Andrey Semashev =D0=BD=D0=B0=D0=BF=D0=B8=D1=
=81=D0=B0:=20
> > > Hi,=20
> > >=20
> > > I wonder if constexpr function arguments would be a useful addition t=
o=20
> the=20
> > >=20
> > > standard. Consider this part of std::atomic interface:=20
> > > template< typename T >=20
> > > void atomic<T>::store(T val, memory_order order)=20
> > > {=20
> > > =20
> > > switch (order)=20
> > > {=20
> > > =20
> > > // implementations with different memory ordering guarantees=20
> > > =20
> > > }=20
> > > =20
> > > }=20
> > >=20
> > > The function itself is not constexpr because the implementation has a=
=20
> > > runtime=20
> > > side effect. However the memory order argument is always constant in=
=20
> > > normal=20
> > > uses and the implementation could have had benefitted from knowing=20
> this=20
> > > constant at compile time. The current standard does not offer means=
=20
> for=20
> > > that,=20
> > > so you're out of luck if the compiler is not smart enough to propagat=
e=20
> > > this=20
> > > constexpr hint behind the scenes. For the most part with compilers I=
=20
> have=20
> > > experience with (gcc, icl, msvc) this only works when the compiler is=
=20
> able=20
> > > to=20
> > > inline the function call.=20
> > >=20
> > > BTW, if anyone wonders if compiler intrinsics help here, no they=20
> don't.=20
> > > With=20
> > >=20
> > > the code similar to this:=20
> > > template< typename T >=20
> > > void atomic<T>::store(T val, memory_order order)=20
> > > {=20
> > > =20
> > > __atomic_store_n(&m_value, val, order);=20
> > > =20
> > > }=20
> > >=20
> > > gcc and icl simply fall back to memory_order_seq_cst regardless of th=
e=20
> > > specified order if they cannot inline the function. This always=20
> happens in=20
> > > debug, for instance.=20
> > >=20
> > > What I'm thinking is if we could require some argument to be constexp=
r=20
> and=20
> > > pass that 'compile-timeness' hint to the function body, the=20
> implementation=20
> > >=20
> > > could optimize better. For example:=20
> > > template< typename T >=20
> > > void atomic<T>::store(T val, constexpr memory_order order)=20
> > > {=20
> > > =20
> > > switch (order) // order is always constexpr=20
> > > {=20
> > > =20
> > > // implementations with different memory ordering guarantees=20
> > > =20
> > > }=20
> > > =20
> > > }=20
> > >=20
> > > In this case the switch/case would always be optimized to a single=20
> case.=20
> > > And=20
> > > the intrinsic-based version would also work as intended. Also, if we=
=20
> have=20
> > > a=20
> > > non-constexpr overload of this function we would also support calling=
=20
> with=20
> > > a=20
> > > runtime value of the memory order (not that it would be of much use=
=20
> > > though).=20
> > >=20
> > > I understand this would have consequences on the ABI because constexp=
r=20
> > > arguments essentiall require to duplicate the function body for each=
=20
> > > constant=20
> > > argument value. It's not a big problem though because we already do=
=20
> that=20
> > > for=20
> > > non-type template parameters.=20
> > >=20
> > > Opinions?=20
>
>
--=20
---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_224_724234951.1428844415939
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">You read my proposal - it does the same thing you want eve=
n if you don't fully understand it.<div><br></div><div>Actually 'constexpr'=
is a useless keyword - it adds nothing to 'inline' functions which most co=
mpilers already optimize out and evaluate at compile-time if possible. Much=
better will be the properties to 'constexpr' to be automatically added to =
each inline function. And what are they actually?</div><div><br></div><div>=
An 'constexpr' function may be evaluated at compile-time (so do 'inline').<=
/div><div><br></div><div>An 'constexpr' function may be used at a constant-=
expression and if so - it's required to be evaluated at compile-time.</div>=
<div><br></div><div><br></div><div>Actually the second line is the so 'BIG'=
difference between those two but I think that it can be implicitly applied=
to all 'inline' functions without any issues (performance or whatever).</d=
iv><div><br></div><div>The part which fulfill your idea is 'inline' variabl=
es which are guaranteed to be evaluated at run-time (as template parameters=
) and more specially 'inline' function parameters (which imply that the fun=
ction they declare/define is 'inline' because templates can't be defined at=
different TU).</div><div><br></div><div>So your example will look like thi=
s by using my construct:</div><div><br></div><div class=3D"prettyprint" sty=
le=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-word; backgrou=
nd-color: rgb(250, 250, 250);"><code class=3D"prettyprint"><div class=3D"su=
bprettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">tem=
plate</span><span style=3D"color: #660;" class=3D"styled-by-prettify"><<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an style=3D"color: #008;" class=3D"styled-by-prettify">typename</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"> T </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">></span><span style=3D"co=
lor: #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"> atomic</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify"><</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify">T</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">>::</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">store</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
>T val</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span=
style=3D"color: #008;" class=3D"styled-by-prettify">inline</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> memory_order order</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> <br> </span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> <br> </span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">switch</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify">order</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-pret=
tify">// order is always constexpr </span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"><br> </span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> <br> </span><span style=3D"col=
or: #800;" class=3D"styled-by-prettify">// implementations with different m=
emory ordering guarantees </span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> <br><br> </span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">}</span></div></code></div><div><br>With the exact sam=
e semantics you want. Function parameter '<span style=3D"color: rgb(0, 0, 0=
); font-family: monospace; background-color: rgb(250, 250, 250);">order</sp=
an>' will accept only constant-expressions and it will be evaluated at comp=
ile-time. Actually those semantics are possible now too but have different =
syntax(etc. by using template parameters):<br><br><span class=3D"styled-by-=
prettify" style=3D"font-family: monospace; color: rgb(0, 0, 136); backgroun=
d-color: rgb(250, 250, 250);"></span></div><div class=3D"prettyprint" style=
=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-word; background=
-color: rgb(250, 250, 250);"><code class=3D"prettyprint"><div class=3D"subp=
rettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">templ=
ate</span><span style=3D"color: #660;" class=3D"styled-by-prettify"><</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span=
style=3D"color: #008;" class=3D"styled-by-prettify">typename</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> T</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> memory_order order </span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">></span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> <br> </span><span style=3D"col=
or: #008;" class=3D"styled-by-prettify">void</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> atomic</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify"><</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify">T</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">>::</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify">store</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">T =
val</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> <br> </sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> <br> </sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">switch</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify">order</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"styl=
ed-by-prettify">// order is always constexpr </span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"><br> </span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> <br> </span><span st=
yle=3D"color: #800;" class=3D"styled-by-prettify">// implementations with d=
ifferent memory ordering guarantees </span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"><br> </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> <br><br> </span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">}</span></div></code></div><div><span class=
=3D"styled-by-prettify" style=3D"font-family: monospace; color: rgb(102, 10=
2, 0); background-color: rgb(250, 250, 250);"><br></span></div><div>=D0=BD=
=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F, 12 =D0=B0=D0=BF=D1=80=D0=B8=D0=BB 2015 =D0=
=B3., 15:29:21 UTC+3, Andrey Semashev =D0=BD=D0=B0=D0=BF=D0=B8=D1=81=D0=B0:=
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;">On Sunday 12 April 2015 05:09:=
29 Alexander Marinov wrote:
<br>> I already sketched the details of this idea. You can read it here
<br>> <<a href=3D"https://groups.google.com/a/isocpp.org/forum/#!topi=
c/std-proposals/RTss7Uyl" target=3D"_blank" rel=3D"nofollow" onmousedown=3D=
"this.href=3D'https://groups.google.com/a/isocpp.org/forum/#!topic/std-prop=
osals/RTss7Uyl';return true;" onclick=3D"this.href=3D'https://groups.google=
..com/a/isocpp.org/forum/#!topic/std-proposals/RTss7Uyl';return true;">https=
://groups.google.com/a/<wbr>isocpp.org/forum/#!topic/std-<wbr>proposals/RTs=
s7Uyl</a>
<br>> zgQ>. Only someone needs to write a proposal and/or implement i=
t as a demo
<br>> in some open-source compiler (GCC or Clang).
<br>
<br>No, I don't think your proposal is related to my idea. I'm not trying t=
o make=20
<br>a function constexpr, I'm trying to propagate compile-time nature of so=
me of=20
<br>its arguments to its body, which is executed in run time.
<br>
<br>(offtopic: And I do think that inline and constexpr are different prope=
rties=20
<br>of the code, even though they are somewhat related on the implementatio=
n side;=20
<br>I do not think they should be mixed together in a single keyword.)
<br>
<br>> =D0=BD=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F, 12 =D0=B0=D0=BF=D1=80=D0=B8=
=D0=BB 2015 =D0=B3., 13:33:17 UTC+3, Andrey Semashev =D0=BD=D0=B0=D0=BF=D0=
=B8=D1=81=D0=B0:
<br>> > Hi,
<br>> >=20
<br>> > I wonder if constexpr function arguments would be a useful ad=
dition to the
<br>> >=20
<br>> > standard. Consider this part of std::atomic interface:
<br>> > template< typename T >
<br>> > void atomic<T>::store(T val, memory_order order)
<br>> > {
<br>> > =20
<br>> > switch (order)
<br>> > {
<br>> > =20
<br>> > // implementations with different memory=
ordering guarantees
<br>> > =20
<br>> > }
<br>> > =20
<br>> > }
<br>> >=20
<br>> > The function itself is not constexpr because the implementati=
on has a
<br>> > runtime
<br>> > side effect. However the memory order argument is always cons=
tant in
<br>> > normal
<br>> > uses and the implementation could have had benefitted from kn=
owing this
<br>> > constant at compile time. The current standard does not offer=
means for
<br>> > that,
<br>> > so you're out of luck if the compiler is not smart enough to =
propagate
<br>> > this
<br>> > constexpr hint behind the scenes. For the most part with comp=
ilers I have
<br>> > experience with (gcc, icl, msvc) this only works when the com=
piler is able
<br>> > to
<br>> > inline the function call.
<br>> >=20
<br>> > BTW, if anyone wonders if compiler intrinsics help here, no t=
hey don't.
<br>> > With
<br>> >=20
<br>> > the code similar to this:
<br>> > template< typename T >
<br>> > void atomic<T>::store(T val, memory_order order)
<br>> > {
<br>> > =20
<br>> > __atomic_store_n(&m_value, val, order);
<br>> > =20
<br>> > }
<br>> >=20
<br>> > gcc and icl simply fall back to memory_order_seq_cst regardle=
ss of the
<br>> > specified order if they cannot inline the function. This alwa=
ys happens in
<br>> > debug, for instance.
<br>> >=20
<br>> > What I'm thinking is if we could require some argument to be =
constexpr and
<br>> > pass that 'compile-timeness' hint to the function body, the i=
mplementation
<br>> >=20
<br>> > could optimize better. For example:
<br>> > template< typename T >
<br>> > void atomic<T>::store(T val, constexpr memory_or=
der order)
<br>> > {
<br>> > =20
<br>> > switch (order) // order is always constexpr
<br>> > {
<br>> > =20
<br>> > // implementations with different memory=
ordering guarantees
<br>> > =20
<br>> > }
<br>> > =20
<br>> > }
<br>> >=20
<br>> > In this case the switch/case would always be optimized to a s=
ingle case.
<br>> > And
<br>> > the intrinsic-based version would also work as intended. Also=
, if we have
<br>> > a
<br>> > non-constexpr overload of this function we would also support=
calling with
<br>> > a
<br>> > runtime value of the memory order (not that it would be of mu=
ch use
<br>> > though).
<br>> >=20
<br>> > I understand this would have consequences on the ABI because =
constexpr
<br>> > arguments essentiall require to duplicate the function body f=
or each
<br>> > constant
<br>> > argument value. It's not a big problem though because we alre=
ady do that
<br>> > for
<br>> > non-type template parameters.
<br>> >=20
<br>> > Opinions?
<br>
<br></blockquote></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_224_724234951.1428844415939--
------=_Part_223_1997393265.1428844415939--
.
Author: Andrey Semashev <andrey.semashev@gmail.com>
Date: Sun, 12 Apr 2015 17:16:01 +0300
Raw View
On Sunday 12 April 2015 06:13:35 Alexander Marinov wrote:
> You read my proposal - it does the same thing you want even if you don't
> fully understand it.
I did read it, and I still don't think it covers my case. In fact, I'm not=
=20
sure I agree with your proposal.
> Actually 'constexpr' is a useless keyword - it adds nothing to 'inline'
> functions which most compilers already optimize out and evaluate at
> compile-time if possible.
It adds a _requirement_ on the function to be evaluated at compile time,=20
provided that its arguments are also constexpr. It also adds certain=20
restrictions on the function body. There is no such requirement or=20
restrictions for inline functions, and in fact even the most trivial inline=
=20
functions are allowed to not be inlined or optimized. And this is the case =
in=20
debug builds, for instance, when compilers don't do any inlining at all but=
=20
are still bound to evaluate constexpr at compile time.
What you're suggesting is essentially mandate a certain level of compiler=
=20
optimization as a language feature. I'm not sure this is a good idea.
> The part which fulfill your idea is 'inline' variables which are guarante=
ed
> to be evaluated at run-time (as template parameters)
I assume, you meant "compile-time" here?
> and more specially
> 'inline' function parameters (which imply that the function they
> declare/define is 'inline' because templates can't be defined at differen=
t
> TU).
>=20
> So your example will look like this by using my construct:
>=20
> template< typename T >
> void atomic<T>::store(T val, inline memory_order order)
> {
> switch (order) // order is always constexpr
> {
> // implementations with different memory ordering guarantees
> }
>=20
> }
>=20
> With the exact same semantics you want. Function parameter 'order' will
> accept only constant-expressions and it will be evaluated at compile-time=
..
Yes, that would be my proposal, although I would still use constexpr keywor=
d.=20
I didn't find inline variables in your proposal thread, sorry if I missed i=
t.
> Actually those semantics are possible now too but have different
> syntax(etc. by using template parameters):
>=20
> template< typename T, memory_order order >
> void atomic<T>::store(T val)
> {
> switch (order) // order is always constexpr
> {
> // implementations with different memory ordering guarantees
> }
>=20
> }
Sure. In fact, I would have defined std::atomic interface this way myself i=
n=20
the first place. I guess, we have it defined the way it is to support C-sty=
le=20
interface? Anyway, we have what we have, and my proposal attempts to improv=
e=20
it.
> =D0=BD=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F, 12 =D0=B0=D0=BF=D1=80=D0=B8=D0=BB 2=
015 =D0=B3., 15:29:21 UTC+3, Andrey Semashev =D0=BD=D0=B0=D0=BF=D0=B8=D1=81=
=D0=B0:
> > On Sunday 12 April 2015 05:09:29 Alexander Marinov wrote:
> > > I already sketched the details of this idea. You can read it here
> > > <
> >=20
> > https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/RTss=
7Uy
> > l
> >=20
> > > zgQ>. Only someone needs to write a proposal and/or implement it as a
> >=20
> > demo
> >=20
> > > in some open-source compiler (GCC or Clang).
> >=20
> > No, I don't think your proposal is related to my idea. I'm not trying t=
o
> > make
> > a function constexpr, I'm trying to propagate compile-time nature of so=
me
> > of
> > its arguments to its body, which is executed in run time.
> >=20
> > (offtopic: And I do think that inline and constexpr are different
> > properties
> > of the code, even though they are somewhat related on the implementatio=
n
> > side;
> > I do not think they should be mixed together in a single keyword.)
> >=20
> > > =D0=BD=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F, 12 =D0=B0=D0=BF=D1=80=D0=B8=D0=
=BB 2015 =D0=B3., 13:33:17 UTC+3, Andrey Semashev =D0=BD=D0=B0=D0=BF=D0=B8=
=D1=81=D0=B0:
> > > > Hi,
> > > >=20
> > > > I wonder if constexpr function arguments would be a useful addition=
to
> >=20
> > the
> >=20
> > > > standard. Consider this part of std::atomic interface:
> > > > template< typename T >
> > > > void atomic<T>::store(T val, memory_order order)
> > > > {
> > > > =20
> > > > switch (order)
> > > > {
> > > > =20
> > > > // implementations with different memory ordering guarantees
> > > > =20
> > > > }
> > > > =20
> > > > }
> > > >=20
> > > > The function itself is not constexpr because the implementation has=
a
> > > > runtime
> > > > side effect. However the memory order argument is always constant i=
n
> > > > normal
> > > > uses and the implementation could have had benefitted from knowing
> >=20
> > this
> >=20
> > > > constant at compile time. The current standard does not offer means
> >=20
> > for
> >=20
> > > > that,
> > > > so you're out of luck if the compiler is not smart enough to propag=
ate
> > > > this
> > > > constexpr hint behind the scenes. For the most part with compilers =
I
> >=20
> > have
> >=20
> > > > experience with (gcc, icl, msvc) this only works when the compiler =
is
> >=20
> > able
> >=20
> > > > to
> > > > inline the function call.
> > > >=20
> > > > BTW, if anyone wonders if compiler intrinsics help here, no they
> >=20
> > don't.
> >=20
> > > > With
> > > >=20
> > > > the code similar to this:
> > > > template< typename T >
> > > > void atomic<T>::store(T val, memory_order order)
> > > > {
> > > > =20
> > > > __atomic_store_n(&m_value, val, order);
> > > > =20
> > > > }
> > > >=20
> > > > gcc and icl simply fall back to memory_order_seq_cst regardless of =
the
> > > > specified order if they cannot inline the function. This always
> >=20
> > happens in
> >=20
> > > > debug, for instance.
> > > >=20
> > > > What I'm thinking is if we could require some argument to be conste=
xpr
> >=20
> > and
> >=20
> > > > pass that 'compile-timeness' hint to the function body, the
> >=20
> > implementation
> >=20
> > > > could optimize better. For example:
> > > > template< typename T >
> > > > void atomic<T>::store(T val, constexpr memory_order order)
> > > > {
> > > > =20
> > > > switch (order) // order is always constexpr
> > > > {
> > > > =20
> > > > // implementations with different memory ordering guarantees
> > > > =20
> > > > }
> > > > =20
> > > > }
> > > >=20
> > > > In this case the switch/case would always be optimized to a single
> >=20
> > case.
> >=20
> > > > And
> > > > the intrinsic-based version would also work as intended. Also, if w=
e
> >=20
> > have
> >=20
> > > > a
> > > > non-constexpr overload of this function we would also support calli=
ng
> >=20
> > with
> >=20
> > > > a
> > > > runtime value of the memory order (not that it would be of much use
> > > > though).
> > > >=20
> > > > I understand this would have consequences on the ABI because conste=
xpr
> > > > arguments essentiall require to duplicate the function body for eac=
h
> > > > constant
> > > > argument value. It's not a big problem though because we already do
> >=20
> > that
> >=20
> > > > for
> > > > non-type template parameters.
> > > >=20
> > > > Opinions?
--=20
---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: inkwizytoryankes@gmail.com
Date: Sun, 12 Apr 2015 07:38:59 -0700 (PDT)
Raw View
------=_Part_7_378508221.1428849540019
Content-Type: multipart/alternative;
boundary="----=_Part_8_741107933.1428849540019"
------=_Part_8_741107933.1428849540019
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Then why don't use template parameters?
template< typename T, memory_order order >
void atomic<T>::store(T val)
{
switch (order)
{
// implementations with different memory ordering guarantees
}
}
or if `memory_order` can be group of values with different type:
template< typename T, typename memory_order_t >
void atomic<T>::store(T val, memory_order_t order)
{
switch (memory_order_t::value)
{
// implementations with different memory ordering guarantees
}
}
On Sunday, April 12, 2015 at 2:29:21 PM UTC+2, Andrey Semashev wrote:
>
> On Sunday 12 April 2015 05:09:29 Alexander Marinov wrote:=20
> > I already sketched the details of this idea. You can read it here=20
> > <
> https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/RTss7U=
yl=20
> > zgQ>. Only someone needs to write a proposal and/or implement it as a=
=20
> demo=20
> > in some open-source compiler (GCC or Clang).=20
>
> No, I don't think your proposal is related to my idea. I'm not trying to=
=20
> make=20
> a function constexpr, I'm trying to propagate compile-time nature of some=
=20
> of=20
> its arguments to its body, which is executed in run time.=20
>
> (offtopic: And I do think that inline and constexpr are different=20
> properties=20
> of the code, even though they are somewhat related on the implementation=
=20
> side;=20
> I do not think they should be mixed together in a single keyword.)=20
>
> > =D0=BD=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F, 12 =D0=B0=D0=BF=D1=80=D0=B8=D0=BB=
2015 =D0=B3., 13:33:17 UTC+3, Andrey Semashev =D0=BD=D0=B0=D0=BF=D0=B8=D1=
=81=D0=B0:=20
> > > Hi,=20
> > >=20
> > > I wonder if constexpr function arguments would be a useful addition t=
o=20
> the=20
> > >=20
> > > standard. Consider this part of std::atomic interface:=20
> > > template< typename T >=20
> > > void atomic<T>::store(T val, memory_order order)=20
> > > {=20
> > > =20
> > > switch (order)=20
> > > {=20
> > > =20
> > > // implementations with different memory ordering guarantees=20
> > > =20
> > > }=20
> > > =20
> > > }=20
> > >=20
> > > The function itself is not constexpr because the implementation has a=
=20
> > > runtime=20
> > > side effect. However the memory order argument is always constant in=
=20
> > > normal=20
> > > uses and the implementation could have had benefitted from knowing=20
> this=20
> > > constant at compile time. The current standard does not offer means=
=20
> for=20
> > > that,=20
> > > so you're out of luck if the compiler is not smart enough to propagat=
e=20
> > > this=20
> > > constexpr hint behind the scenes. For the most part with compilers I=
=20
> have=20
> > > experience with (gcc, icl, msvc) this only works when the compiler is=
=20
> able=20
> > > to=20
> > > inline the function call.=20
> > >=20
> > > BTW, if anyone wonders if compiler intrinsics help here, no they=20
> don't.=20
> > > With=20
> > >=20
> > > the code similar to this:=20
> > > template< typename T >=20
> > > void atomic<T>::store(T val, memory_order order)=20
> > > {=20
> > > =20
> > > __atomic_store_n(&m_value, val, order);=20
> > > =20
> > > }=20
> > >=20
> > > gcc and icl simply fall back to memory_order_seq_cst regardless of th=
e=20
> > > specified order if they cannot inline the function. This always=20
> happens in=20
> > > debug, for instance.=20
> > >=20
> > > What I'm thinking is if we could require some argument to be constexp=
r=20
> and=20
> > > pass that 'compile-timeness' hint to the function body, the=20
> implementation=20
> > >=20
> > > could optimize better. For example:=20
> > > template< typename T >=20
> > > void atomic<T>::store(T val, constexpr memory_order order)=20
> > > {=20
> > > =20
> > > switch (order) // order is always constexpr=20
> > > {=20
> > > =20
> > > // implementations with different memory ordering guarantees=20
> > > =20
> > > }=20
> > > =20
> > > }=20
> > >=20
> > > In this case the switch/case would always be optimized to a single=20
> case.=20
> > > And=20
> > > the intrinsic-based version would also work as intended. Also, if we=
=20
> have=20
> > > a=20
> > > non-constexpr overload of this function we would also support calling=
=20
> with=20
> > > a=20
> > > runtime value of the memory order (not that it would be of much use=
=20
> > > though).=20
> > >=20
> > > I understand this would have consequences on the ABI because constexp=
r=20
> > > arguments essentiall require to duplicate the function body for each=
=20
> > > constant=20
> > > argument value. It's not a big problem though because we already do=
=20
> that=20
> > > for=20
> > > non-type template parameters.=20
> > >=20
> > > Opinions?=20
>
>
--=20
---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_8_741107933.1428849540019
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Then why don't use template parameters?<br><div class=3D"p=
rettyprint" style=3D"background-color: rgb(250, 250, 250); border-color: rg=
b(187, 187, 187); border-style: solid; border-width: 1px; word-wrap: break-=
word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"></span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">template</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: #008;" class=3D=
"styled-by-prettify">typename</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> T</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><code class=3D"prettyprint"><span style=3D"color: #660;" class=
=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> memory_order order</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify"></span></code> </span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">></span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">void</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> atomic</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify"><</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">T</span><span style=3D"color: #660;" class=3D"styled-by-prettify">>::=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify">store</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">T val</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br> </span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br> </span><span style=3D"color:=
#008;" class=3D"styled-by-prettify">switch</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">order</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
><br> </span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"><br> </span><span style=3D"color:=
#800;" class=3D"styled-by-prettify">// implementations with different memo=
ry ordering guarantees</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br> </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
><br></span></div></code></div>or if `memory_order` can be group of values =
with different type:<br><div class=3D"prettyprint" style=3D"background-colo=
r: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: soli=
d; border-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><=
div class=3D"subprettyprint"><code class=3D"prettyprint"><span style=3D"col=
or: #008;" class=3D"styled-by-prettify">template</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: #008;" class=
=3D"styled-by-prettify">typename</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> T</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><code class=3D"prettyprint"><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"></span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify"></span></code>, </span></code><code class=3D"prettyprint">=
<code class=3D"prettyprint"><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"color: #000;" class=3D"styled-by-prettify"> =
</span></code></code><code class=3D"prettyprint"><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><code class=3D"prettyprint"><code class=3D"=
prettyprint"><span style=3D"color: #000;" class=3D"styled-by-prettify"><cod=
e class=3D"prettyprint"><code class=3D"prettyprint"><span style=3D"color: #=
000;" class=3D"styled-by-prettify"><code class=3D"prettyprint"><span style=
=3D"color: #000;" class=3D"styled-by-prettify">memory_order_t</span></code>=
</span></code></code></span></code></code> </span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">></span><span style=3D"color: #000;" cl=
ass=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"style=
d-by-prettify"> atomic</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify"><</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">T</span><span style=3D"color: #660;" class=3D"styled-by-prettify">>=
;::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">store</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">T val</span></code><c=
ode class=3D"prettyprint"><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><code class=3D"prettyprint"><code class=3D"prettyprint"><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><code class=3D"prettyprint"=
><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> memory_order_t order</sp=
an></code></span></code></code></span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br> </span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><b=
r> </span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">switch</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">(<=
/span></code><code class=3D"prettyprint"><span style=3D"color: #660;" class=
=3D"styled-by-prettify"><code class=3D"prettyprint"><code class=3D"prettypr=
int"><code class=3D"prettyprint"><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"></span></code></code><code class=3D"prettyprint"><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><code class=3D"prettyprint"=
><code class=3D"prettyprint"><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><code class=3D"prettyprint"><code class=3D"prettyprint"><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><code class=3D"prettypri=
nt"><span style=3D"color: #000;" class=3D"styled-by-prettify">memory_order_=
t::value</span></code></span></code></code></span></code></code></span></co=
de></code></span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br> =
; </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&=
nbsp; </span><span style=3D"color: #800;" cl=
ass=3D"styled-by-prettify">// implementations with different memory orderin=
g guarantees</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><br> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></spa=
n></code><span style=3D"color: #660;" class=3D"styled-by-prettify"></span><=
/div></code></div><br><br><br>On Sunday, April 12, 2015 at 2:29:21 PM UTC+2=
, Andrey Semashev wrote:<blockquote class=3D"gmail_quote" style=3D"margin: =
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Sun=
day 12 April 2015 05:09:29 Alexander Marinov wrote:
<br>> I already sketched the details of this idea. You can read it here
<br>> <<a href=3D"https://groups.google.com/a/isocpp.org/forum/#!topi=
c/std-proposals/RTss7Uyl" target=3D"_blank" rel=3D"nofollow" onmousedown=3D=
"this.href=3D'https://groups.google.com/a/isocpp.org/forum/#!topic/std-prop=
osals/RTss7Uyl';return true;" onclick=3D"this.href=3D'https://groups.google=
..com/a/isocpp.org/forum/#!topic/std-proposals/RTss7Uyl';return true;">https=
://groups.google.com/a/<wbr>isocpp.org/forum/#!topic/std-<wbr>proposals/RTs=
s7Uyl</a>
<br>> zgQ>. Only someone needs to write a proposal and/or implement i=
t as a demo
<br>> in some open-source compiler (GCC or Clang).
<br>
<br>No, I don't think your proposal is related to my idea. I'm not trying t=
o make=20
<br>a function constexpr, I'm trying to propagate compile-time nature of so=
me of=20
<br>its arguments to its body, which is executed in run time.
<br>
<br>(offtopic: And I do think that inline and constexpr are different prope=
rties=20
<br>of the code, even though they are somewhat related on the implementatio=
n side;=20
<br>I do not think they should be mixed together in a single keyword.)
<br>
<br>> =D0=BD=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F, 12 =D0=B0=D0=BF=D1=80=D0=B8=
=D0=BB 2015 =D0=B3., 13:33:17 UTC+3, Andrey Semashev =D0=BD=D0=B0=D0=BF=D0=
=B8=D1=81=D0=B0:
<br>> > Hi,
<br>> >=20
<br>> > I wonder if constexpr function arguments would be a useful ad=
dition to the
<br>> >=20
<br>> > standard. Consider this part of std::atomic interface:
<br>> > template< typename T >
<br>> > void atomic<T>::store(T val, memory_order order)
<br>> > {
<br>> > =20
<br>> > switch (order)
<br>> > {
<br>> > =20
<br>> > // implementations with different memory=
ordering guarantees
<br>> > =20
<br>> > }
<br>> > =20
<br>> > }
<br>> >=20
<br>> > The function itself is not constexpr because the implementati=
on has a
<br>> > runtime
<br>> > side effect. However the memory order argument is always cons=
tant in
<br>> > normal
<br>> > uses and the implementation could have had benefitted from kn=
owing this
<br>> > constant at compile time. The current standard does not offer=
means for
<br>> > that,
<br>> > so you're out of luck if the compiler is not smart enough to =
propagate
<br>> > this
<br>> > constexpr hint behind the scenes. For the most part with comp=
ilers I have
<br>> > experience with (gcc, icl, msvc) this only works when the com=
piler is able
<br>> > to
<br>> > inline the function call.
<br>> >=20
<br>> > BTW, if anyone wonders if compiler intrinsics help here, no t=
hey don't.
<br>> > With
<br>> >=20
<br>> > the code similar to this:
<br>> > template< typename T >
<br>> > void atomic<T>::store(T val, memory_order order)
<br>> > {
<br>> > =20
<br>> > __atomic_store_n(&m_value, val, order);
<br>> > =20
<br>> > }
<br>> >=20
<br>> > gcc and icl simply fall back to memory_order_seq_cst regardle=
ss of the
<br>> > specified order if they cannot inline the function. This alwa=
ys happens in
<br>> > debug, for instance.
<br>> >=20
<br>> > What I'm thinking is if we could require some argument to be =
constexpr and
<br>> > pass that 'compile-timeness' hint to the function body, the i=
mplementation
<br>> >=20
<br>> > could optimize better. For example:
<br>> > template< typename T >
<br>> > void atomic<T>::store(T val, constexpr memory_or=
der order)
<br>> > {
<br>> > =20
<br>> > switch (order) // order is always constexpr
<br>> > {
<br>> > =20
<br>> > // implementations with different memory=
ordering guarantees
<br>> > =20
<br>> > }
<br>> > =20
<br>> > }
<br>> >=20
<br>> > In this case the switch/case would always be optimized to a s=
ingle case.
<br>> > And
<br>> > the intrinsic-based version would also work as intended. Also=
, if we have
<br>> > a
<br>> > non-constexpr overload of this function we would also support=
calling with
<br>> > a
<br>> > runtime value of the memory order (not that it would be of mu=
ch use
<br>> > though).
<br>> >=20
<br>> > I understand this would have consequences on the ABI because =
constexpr
<br>> > arguments essentiall require to duplicate the function body f=
or each
<br>> > constant
<br>> > argument value. It's not a big problem though because we alre=
ady do that
<br>> > for
<br>> > non-type template parameters.
<br>> >=20
<br>> > Opinions?
<br>
<br></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_8_741107933.1428849540019--
------=_Part_7_378508221.1428849540019--
.
Author: Marcelo Zimbres <mzimbres@gmail.com>
Date: Sun, 12 Apr 2015 12:03:46 -0300
Raw View
"I wonder if constexpr function arguments would be a useful addition to the
standard."
I would like to see this into the standard. My motivation is that I would l=
ike
to detect at compile time, whether the allocate member function of some
allocator is used with n different than one 1. For example, say I have:
std::list<int, my::allocator<int>> foo;
I would like to raise a compiler error (or take appropriate action)
if my::allocator<int>::allocate(n) is used with n !=3D 1 inside std::list.
my::allocator<int>::allocate(1) // This is fine.
my::allocator<int>::allocate(2) // Should be detected at compile time.
my::allocator<int>::allocate(n) // Runtime value should be also detected.
I think your proposal would allow me to do this.
Marcelo
2015-04-12 11:38 GMT-03:00 <inkwizytoryankes@gmail.com>:
> Then why don't use template parameters?
> template< typename T, memory_order order >
> void atomic<T>::store(T val)
> {
> switch (order)
> {
> // implementations with different memory ordering guarantees
> }
> }
> or if `memory_order` can be group of values with different type:
> template< typename T, typename memory_order_t >
> void atomic<T>::store(T val, memory_order_t order)
> {
> switch (memory_order_t::value)
> {
> // implementations with different memory ordering guarantees
> }
> }
>
>
>
> On Sunday, April 12, 2015 at 2:29:21 PM UTC+2, Andrey Semashev wrote:
>>
>> On Sunday 12 April 2015 05:09:29 Alexander Marinov wrote:
>> > I already sketched the details of this idea. You can read it here
>> >
>> > <https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/RT=
ss7Uyl
>> > zgQ>. Only someone needs to write a proposal and/or implement it as a
>> > demo
>> > in some open-source compiler (GCC or Clang).
>>
>> No, I don't think your proposal is related to my idea. I'm not trying to
>> make
>> a function constexpr, I'm trying to propagate compile-time nature of som=
e
>> of
>> its arguments to its body, which is executed in run time.
>>
>> (offtopic: And I do think that inline and constexpr are different
>> properties
>> of the code, even though they are somewhat related on the implementation
>> side;
>> I do not think they should be mixed together in a single keyword.)
>>
>> > =D0=BD=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F, 12 =D0=B0=D0=BF=D1=80=D0=B8=D0=
=BB 2015 =D0=B3., 13:33:17 UTC+3, Andrey Semashev =D0=BD=D0=B0=D0=BF=D0=B8=
=D1=81=D0=B0:
>> > > Hi,
>> > >
>> > > I wonder if constexpr function arguments would be a useful addition =
to
>> > > the
>> > >
>> > > standard. Consider this part of std::atomic interface:
>> > > template< typename T >
>> > > void atomic<T>::store(T val, memory_order order)
>> > > {
>> > >
>> > > switch (order)
>> > > {
>> > >
>> > > // implementations with different memory ordering guarantees
>> > >
>> > > }
>> > >
>> > > }
>> > >
>> > > The function itself is not constexpr because the implementation has =
a
>> > > runtime
>> > > side effect. However the memory order argument is always constant in
>> > > normal
>> > > uses and the implementation could have had benefitted from knowing
>> > > this
>> > > constant at compile time. The current standard does not offer means
>> > > for
>> > > that,
>> > > so you're out of luck if the compiler is not smart enough to propaga=
te
>> > > this
>> > > constexpr hint behind the scenes. For the most part with compilers I
>> > > have
>> > > experience with (gcc, icl, msvc) this only works when the compiler i=
s
>> > > able
>> > > to
>> > > inline the function call.
>> > >
>> > > BTW, if anyone wonders if compiler intrinsics help here, no they
>> > > don't.
>> > > With
>> > >
>> > > the code similar to this:
>> > > template< typename T >
>> > > void atomic<T>::store(T val, memory_order order)
>> > > {
>> > >
>> > > __atomic_store_n(&m_value, val, order);
>> > >
>> > > }
>> > >
>> > > gcc and icl simply fall back to memory_order_seq_cst regardless of t=
he
>> > > specified order if they cannot inline the function. This always
>> > > happens in
>> > > debug, for instance.
>> > >
>> > > What I'm thinking is if we could require some argument to be constex=
pr
>> > > and
>> > > pass that 'compile-timeness' hint to the function body, the
>> > > implementation
>> > >
>> > > could optimize better. For example:
>> > > template< typename T >
>> > > void atomic<T>::store(T val, constexpr memory_order order)
>> > > {
>> > >
>> > > switch (order) // order is always constexpr
>> > > {
>> > >
>> > > // implementations with different memory ordering guarantees
>> > >
>> > > }
>> > >
>> > > }
>> > >
>> > > In this case the switch/case would always be optimized to a single
>> > > case.
>> > > And
>> > > the intrinsic-based version would also work as intended. Also, if we
>> > > have
>> > > a
>> > > non-constexpr overload of this function we would also support callin=
g
>> > > with
>> > > a
>> > > runtime value of the memory order (not that it would be of much use
>> > > though).
>> > >
>> > > I understand this would have consequences on the ABI because constex=
pr
>> > > arguments essentiall require to duplicate the function body for each
>> > > constant
>> > > argument value. It's not a big problem though because we already do
>> > > that
>> > > for
>> > > non-type template parameters.
>> > >
>> > > Opinions?
>>
> --
>
> ---
> 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.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
--=20
---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Alexander Marinov <sasho648@mail.bg>
Date: Sun, 12 Apr 2015 08:34:51 -0700 (PDT)
Raw View
------=_Part_299_1292937151.1428852891915
Content-Type: multipart/alternative;
boundary="----=_Part_300_7672864.1428852891915"
------=_Part_300_7672864.1428852891915
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
=D0=BD=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F, 12 =D0=B0=D0=BF=D1=80=D0=B8=D0=BB 201=
5 =D0=B3., 17:16:09 UTC+3, Andrey Semashev =D0=BD=D0=B0=D0=BF=D0=B8=D1=81=
=D0=B0:
>
> On Sunday 12 April 2015 06:13:35 Alexander Marinov wrote:=20
> > You read my proposal - it does the same thing you want even if you don'=
t=20
> > fully understand it.=20
>
> I did read it, and I still don't think it covers my case. In fact, I'm no=
t=20
> sure I agree with your proposal.=20
>
> > Actually 'constexpr' is a useless keyword - it adds nothing to 'inline'=
=20
> > functions which most compilers already optimize out and evaluate at=20
> > compile-time if possible.=20
>
> It adds a _requirement_ on the function to be evaluated at compile time,=
=20
> provided that its arguments are also constexpr. It also adds certain=20
> restrictions on the function body. There is no such requirement or=20
> restrictions for inline functions, and in fact even the most trivial=20
> inline=20
> functions are allowed to not be inlined or optimized. And this is the cas=
e=20
> in=20
> debug builds, for instance, when compilers don't do any inlining at all=
=20
> but=20
> are still bound to evaluate constexpr at compile time.=20
>
Actually it doesn't, neither 'constexpr' do. A call to 'constexpr' is done=
=20
the same way to a normal function so it's still a compiler decision if it's=
=20
going to evaluate it at compile-time. The only case where this is required=
=20
is when such function is instanced at place where constant-expression is=20
expected. I don't see any reason not to implicitly enable this feature to=
=20
'inline' functions too. Actually 'constexpr' functions are inline by=20
default. Examples of current standard:
constexpr /*imagine < this was not there */ inline int func(int a) { return=
=20
a * 4; }
//note the above declaration is the same if 'inline' was not there because=
=20
it's implicitly implied by 'constexpr'
int b;
int main(){
float arr[func(b)]; //here 'func' should be evaluated at compile-time=
=20
but this is currently not possible - error
int runtime =3D func(b); //ok, here 'func(b)' is evaluated at 'run-time=
'
float arr1[func(9)]; //ok, here 'func(b)' is evaluated at 'compile-time=
'
int compilerdec =3D func(9); //ok, here 'func(b)' is evaluated either a=
t=20
'run-time' or 'compile-time'
}
Note that the above is a real working example. You can test it online here=
=20
<http://melpon.org/wandbox/permlink/xtDvFqwUcIB2nFVT>.
About the function requirements - I really think that they are decided on=
=20
no real basis and I that they should be removed all. At first 'constexpr'=
=20
function should consist only of a return statement, later this requirement=
=20
was lifted. I think now it's high-time to lift them all.
=20
>
> What you're suggesting is essentially mandate a certain level of compiler=
=20
> optimization as a language feature. I'm not sure this is a good idea.=20
>
> > The part which fulfill your idea is 'inline' variables which are=20
> guaranteed=20
> > to be evaluated at run-time (as template parameters)=20
>
> I assume, you meant "compile-time" here?=20
>
Yeah - sorry - common mistake of mine.
=20
>
> > and more specially=20
> > 'inline' function parameters (which imply that the function they=20
> > declare/define is 'inline' because templates can't be defined at=20
> different=20
> > TU).=20
> >=20
> > So your example will look like this by using my construct:=20
> >=20
> > template< typename T >=20
> > void atomic<T>::store(T val, inline memory_order order)=20
> > {=20
> > switch (order) // order is always constexpr=20
> > {=20
> > // implementations with different memory ordering guarantees=20
> > }=20
> >=20
> > }=20
> >=20
> > With the exact same semantics you want. Function parameter 'order' will=
=20
> > accept only constant-expressions and it will be evaluated at=20
> compile-time.=20
>
> Yes, that would be my proposal, although I would still use constexpr=20
> keyword.=20
> I didn't find inline variables in your proposal thread, sorry if I missed=
=20
> it.=20
>
Why polite the source code with another new keyword as we can reuse an=20
existing one.
=20
>
> > Actually those semantics are possible now too but have different=20
> > syntax(etc. by using template parameters):=20
> >=20
> > template< typename T, memory_order order >=20
> > void atomic<T>::store(T val)=20
> > {=20
> > switch (order) // order is always constexpr=20
> > {=20
> > // implementations with different memory ordering guarantees=20
> > }=20
> >=20
> > }=20
>
> Sure. In fact, I would have defined std::atomic interface this way myself=
=20
> in=20
> the first place. I guess, we have it defined the way it is to support=20
> C-style=20
> interface? Anyway, we have what we have, and my proposal attempts to=20
> improve=20
> it.=20
>
> > =D0=BD=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F, 12 =D0=B0=D0=BF=D1=80=D0=B8=D0=BB=
2015 =D0=B3., 15:29:21 UTC+3, Andrey Semashev =D0=BD=D0=B0=D0=BF=D0=B8=D1=
=81=D0=B0:=20
> > > On Sunday 12 April 2015 05:09:29 Alexander Marinov wrote:=20
> > > > I already sketched the details of this idea. You can read it here=
=20
> > > > <=20
> > >=20
> > >=20
> https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/RTss7U=
y=20
> > > l=20
> > >=20
> > > > zgQ>. Only someone needs to write a proposal and/or implement it as=
=20
> a=20
> > >=20
> > > demo=20
> > >=20
> > > > in some open-source compiler (GCC or Clang).=20
> > >=20
> > > No, I don't think your proposal is related to my idea. I'm not trying=
=20
> to=20
> > > make=20
> > > a function constexpr, I'm trying to propagate compile-time nature of=
=20
> some=20
> > > of=20
> > > its arguments to its body, which is executed in run time.=20
> > >=20
> > > (offtopic: And I do think that inline and constexpr are different=20
> > > properties=20
> > > of the code, even though they are somewhat related on the=20
> implementation=20
> > > side;=20
> > > I do not think they should be mixed together in a single keyword.)=20
> > >=20
> > > > =D0=BD=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F, 12 =D0=B0=D0=BF=D1=80=D0=B8=
=D0=BB 2015 =D0=B3., 13:33:17 UTC+3, Andrey Semashev =D0=BD=D0=B0=D0=BF=D0=
=B8=D1=81=D0=B0:=20
> > > > > Hi,=20
> > > > >=20
> > > > > I wonder if constexpr function arguments would be a useful=20
> addition to=20
> > >=20
> > > the=20
> > >=20
> > > > > standard. Consider this part of std::atomic interface:=20
> > > > > template< typename T >=20
> > > > > void atomic<T>::store(T val, memory_order order)=20
> > > > > {=20
> > > > > =20
> > > > > switch (order)=20
> > > > > {=20
> > > > > =20
> > > > > // implementations with different memory ordering guarantee=
s=20
> > > > > =20
> > > > > }=20
> > > > > =20
> > > > > }=20
> > > > >=20
> > > > > The function itself is not constexpr because the implementation=
=20
> has a=20
> > > > > runtime=20
> > > > > side effect. However the memory order argument is always constant=
=20
> in=20
> > > > > normal=20
> > > > > uses and the implementation could have had benefitted from knowin=
g=20
> > >=20
> > > this=20
> > >=20
> > > > > constant at compile time. The current standard does not offer=20
> means=20
> > >=20
> > > for=20
> > >=20
> > > > > that,=20
> > > > > so you're out of luck if the compiler is not smart enough to=20
> propagate=20
> > > > > this=20
> > > > > constexpr hint behind the scenes. For the most part with compiler=
s=20
> I=20
> > >=20
> > > have=20
> > >=20
> > > > > experience with (gcc, icl, msvc) this only works when the compile=
r=20
> is=20
> > >=20
> > > able=20
> > >=20
> > > > > to=20
> > > > > inline the function call.=20
> > > > >=20
> > > > > BTW, if anyone wonders if compiler intrinsics help here, no they=
=20
> > >=20
> > > don't.=20
> > >=20
> > > > > With=20
> > > > >=20
> > > > > the code similar to this:=20
> > > > > template< typename T >=20
> > > > > void atomic<T>::store(T val, memory_order order)=20
> > > > > {=20
> > > > > =20
> > > > > __atomic_store_n(&m_value, val, order);=20
> > > > > =20
> > > > > }=20
> > > > >=20
> > > > > gcc and icl simply fall back to memory_order_seq_cst regardless o=
f=20
> the=20
> > > > > specified order if they cannot inline the function. This always=
=20
> > >=20
> > > happens in=20
> > >=20
> > > > > debug, for instance.=20
> > > > >=20
> > > > > What I'm thinking is if we could require some argument to be=20
> constexpr=20
> > >=20
> > > and=20
> > >=20
> > > > > pass that 'compile-timeness' hint to the function body, the=20
> > >=20
> > > implementation=20
> > >=20
> > > > > could optimize better. For example:=20
> > > > > template< typename T >=20
> > > > > void atomic<T>::store(T val, constexpr memory_order order)=20
> > > > > {=20
> > > > > =20
> > > > > switch (order) // order is always constexpr=20
> > > > > {=20
> > > > > =20
> > > > > // implementations with different memory ordering guarantee=
s=20
> > > > > =20
> > > > > }=20
> > > > > =20
> > > > > }=20
> > > > >=20
> > > > > In this case the switch/case would always be optimized to a singl=
e=20
> > >=20
> > > case.=20
> > >=20
> > > > > And=20
> > > > > the intrinsic-based version would also work as intended. Also, if=
=20
> we=20
> > >=20
> > > have=20
> > >=20
> > > > > a=20
> > > > > non-constexpr overload of this function we would also support=20
> calling=20
> > >=20
> > > with=20
> > >=20
> > > > > a=20
> > > > > runtime value of the memory order (not that it would be of much=
=20
> use=20
> > > > > though).=20
> > > > >=20
> > > > > I understand this would have consequences on the ABI because=20
> constexpr=20
> > > > > arguments essentiall require to duplicate the function body for=
=20
> each=20
> > > > > constant=20
> > > > > argument value. It's not a big problem though because we already=
=20
> do=20
> > >=20
> > > that=20
> > >=20
> > > > > for=20
> > > > > non-type template parameters.=20
> > > > >=20
> > > > > Opinions?=20
>
>
--=20
---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_300_7672864.1428852891915
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>=D0=BD=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F, 12 =D0=B0=D0=
=BF=D1=80=D0=B8=D0=BB 2015 =D0=B3., 17:16:09 UTC+3, Andrey Semashev =D0=BD=
=D0=B0=D0=BF=D0=B8=D1=81=D0=B0:<blockquote class=3D"gmail_quote" style=3D"m=
argin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"=
>On Sunday 12 April 2015 06:13:35 Alexander Marinov wrote:
<br>> You read my proposal - it does the same thing you want even if you=
don't
<br>> fully understand it.
<br>
<br>I did read it, and I still don't think it covers my case. In fact, I'm =
not=20
<br>sure I agree with your proposal.
<br>
<br>> Actually 'constexpr' is a useless keyword - it adds nothing to 'in=
line'
<br>> functions which most compilers already optimize out and evaluate a=
t
<br>> compile-time if possible.
<br>
<br>It adds a _requirement_ on the function to be evaluated at compile time=
,=20
<br>provided that its arguments are also constexpr. It also adds certain=20
<br>restrictions on the function body. There is no such requirement or=20
<br>restrictions for inline functions, and in fact even the most trivial in=
line=20
<br>functions are allowed to not be inlined or optimized. And this is the c=
ase in=20
<br>debug builds, for instance, when compilers don't do any inlining at all=
but=20
<br>are still bound to evaluate constexpr at compile time.
<br></blockquote><div><br></div><div>Actually it doesn't, neither 'constexp=
r' do. A call to 'constexpr' is done the same way to a normal function so i=
t's still a compiler decision if it's going to evaluate it at compile-time.=
The only case where this is required is when such function is instanced at=
place where constant-expression is expected. I don't see any reason not to=
implicitly enable this feature to 'inline' functions too. Actually 'conste=
xpr' functions are inline by default. Examples of current standard:<br><br>=
</div><div><div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 1=
87, 187); word-wrap: break-word; background-color: rgb(250, 250, 250);"><co=
de class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color=
: #008;" class=3D"styled-by-prettify">constexpr</span><span style=3D"color:=
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #800;" c=
lass=3D"styled-by-prettify">/*imagine < this was not there */</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">inline</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #0=
08;" class=3D"styled-by-prettify">int</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> func</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">int</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> a</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-by-prettify">{</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">return</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> a </span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">*</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: #066;" class=3D"styled-by-=
prettify">4</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-by-prettify">}</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br><br></span><span style=
=3D"color: #800;" class=3D"styled-by-prettify">//note the above declaration=
is the same if 'inline' was not there because it's implicitly implied by '=
constexpr'</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">in=
t</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> b</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br><br></span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">int</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> main</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">(){</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br> </span><span style=3D"color: =
#008;" class=3D"styled-by-prettify">float</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> arr</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">[</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify">func</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
>b</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)];</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: #800;" class=3D"styled-by-prettify">//here 'func' should be =
evaluated at compile-time but this is currently not possible - error</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br><br> =
; </span><span style=3D"color: #008;" class=3D"styled-by-prettify">i=
nt</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> runtime=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> func</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">b</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">//ok, here 'func(b)' is evaluated at 'run-time'</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br><br> =
; </span><span style=3D"color: #008;" class=3D"styled-by-prettify">f=
loat</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> arr1<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">[</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify">func</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"col=
or: #066;" class=3D"styled-by-prettify">9</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"style=
d-by-prettify">//ok, here 'func(b)' is evaluated at 'compile-time'</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br><br> &nbs=
p; </span><span style=3D"color: #008;" class=3D"styled-by-prettify">int</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> compilerdec <=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> func</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"=
color: #066;" class=3D"styled-by-prettify">9</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">//ok, here 'func(b)' is evaluated either at 'run-time' or =
'compile-time'</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"><br><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">}</span></div></code></div><div><br></div></div><div>Note that the above =
is a real working example. You can test it online <a href=3D"http://melpon.=
org/wandbox/permlink/xtDvFqwUcIB2nFVT">here</a>.</div><div><br></div><div>A=
bout the function requirements - I really think that they are decided on no=
real basis and I that they should be removed all. At first 'constexpr' fun=
ction should consist only of a return statement, later this requirement was=
lifted. I think now it's high-time to lift them all.</div><div> </div=
><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bo=
rder-left: 1px #ccc solid;padding-left: 1ex;">
<br>What you're suggesting is essentially mandate a certain level of compil=
er=20
<br>optimization as a language feature. I'm not sure this is a good idea.
<br>
<br>> The part which fulfill your idea is 'inline' variables which are g=
uaranteed
<br>> to be evaluated at run-time (as template parameters)
<br>
<br>I assume, you meant "compile-time" here?
<br></blockquote><div><br></div><div>Yeah - sorry - common mistake of mine.=
</div><div> </div><blockquote class=3D"gmail_quote" style=3D"margin: 0=
;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<br>> and more specially
<br>> 'inline' function parameters (which imply that the function they
<br>> declare/define is 'inline' because templates can't be defined at d=
ifferent
<br>> TU).
<br>>=20
<br>> So your example will look like this by using my construct:
<br>>=20
<br>> template< typename T >
<br>> void atomic<T>::store(T val, inline memory_order orde=
r)
<br>> {
<br>> switch (order) // order is always constexpr
<br>> {
<br>> // implementations with different memory orde=
ring guarantees
<br>> }
<br>>=20
<br>> }
<br>>=20
<br>> With the exact same semantics you want. Function parameter 'order'=
will
<br>> accept only constant-expressions and it will be evaluated at compi=
le-time.
<br>
<br>Yes, that would be my proposal, although I would still use constexpr ke=
yword.=20
<br>I didn't find inline variables in your proposal thread, sorry if I miss=
ed it.
<br></blockquote><div><br></div><div>Why polite the source code with anothe=
r new keyword as we can reuse an existing one.</div><div> </div><block=
quote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-le=
ft: 1px #ccc solid;padding-left: 1ex;">
<br>> Actually those semantics are possible now too but have different
<br>> syntax(etc. by using template parameters):
<br>>=20
<br>> template< typename T, memory_order order >
<br>> void atomic<T>::store(T val)
<br>> {
<br>> switch (order) // order is always constexpr
<br>> {
<br>> // implementations with different memory orde=
ring guarantees
<br>> }
<br>>=20
<br>> }
<br>
<br>Sure. In fact, I would have defined std::atomic interface this way myse=
lf in=20
<br>the first place. I guess, we have it defined the way it is to support C=
-style=20
<br>interface? Anyway, we have what we have, and my proposal attempts to im=
prove=20
<br>it.
<br>
<br>> =D0=BD=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F, 12 =D0=B0=D0=BF=D1=80=D0=B8=
=D0=BB 2015 =D0=B3., 15:29:21 UTC+3, Andrey Semashev =D0=BD=D0=B0=D0=BF=D0=
=B8=D1=81=D0=B0:
<br>> > On Sunday 12 April 2015 05:09:29 Alexander Marinov wrote:
<br>> > > I already sketched the details of this idea. You can rea=
d it here
<br>> > > <
<br>> >=20
<br>> > <a href=3D"https://groups.google.com/a/isocpp.org/forum/#!top=
ic/std-proposals/RTss7Uy" target=3D"_blank" rel=3D"nofollow" onmousedown=3D=
"this.href=3D'https://groups.google.com/a/isocpp.org/forum/#!topic/std-prop=
osals/RTss7Uy';return true;" onclick=3D"this.href=3D'https://groups.google.=
com/a/isocpp.org/forum/#!topic/std-proposals/RTss7Uy';return true;">https:/=
/groups.google.com/a/<wbr>isocpp.org/forum/#!topic/std-<wbr>proposals/RTss7=
Uy</a>
<br>> > l
<br>> >=20
<br>> > > zgQ>. Only someone needs to write a proposal and/or i=
mplement it as a
<br>> >=20
<br>> > demo
<br>> >=20
<br>> > > in some open-source compiler (GCC or Clang).
<br>> >=20
<br>> > No, I don't think your proposal is related to my idea. I'm no=
t trying to
<br>> > make
<br>> > a function constexpr, I'm trying to propagate compile-time na=
ture of some
<br>> > of
<br>> > its arguments to its body, which is executed in run time.
<br>> >=20
<br>> > (offtopic: And I do think that inline and constexpr are diffe=
rent
<br>> > properties
<br>> > of the code, even though they are somewhat related on the imp=
lementation
<br>> > side;
<br>> > I do not think they should be mixed together in a single keyw=
ord.)
<br>> >=20
<br>> > > =D0=BD=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F, 12 =D0=B0=D0=BF=D1=
=80=D0=B8=D0=BB 2015 =D0=B3., 13:33:17 UTC+3, Andrey Semashev =D0=BD=D0=B0=
=D0=BF=D0=B8=D1=81=D0=B0:
<br>> > > > Hi,
<br>> > > >=20
<br>> > > > I wonder if constexpr function arguments would be a=
useful addition to
<br>> >=20
<br>> > the
<br>> >=20
<br>> > > > standard. Consider this part of std::atomic interfa=
ce:
<br>> > > > template< typename T >
<br>> > > > void atomic<T>::store(T val, memory_or=
der order)
<br>> > > > {
<br>> > > > =20
<br>> > > > switch (order)
<br>> > > > {
<br>> > > > =20
<br>> > > > // implementations with differ=
ent memory ordering guarantees
<br>> > > > =20
<br>> > > > }
<br>> > > > =20
<br>> > > > }
<br>> > > >=20
<br>> > > > The function itself is not constexpr because the im=
plementation has a
<br>> > > > runtime
<br>> > > > side effect. However the memory order argument is a=
lways constant in
<br>> > > > normal
<br>> > > > uses and the implementation could have had benefitt=
ed from knowing
<br>> >=20
<br>> > this
<br>> >=20
<br>> > > > constant at compile time. The current standard does=
not offer means
<br>> >=20
<br>> > for
<br>> >=20
<br>> > > > that,
<br>> > > > so you're out of luck if the compiler is not smart =
enough to propagate
<br>> > > > this
<br>> > > > constexpr hint behind the scenes. For the most part=
with compilers I
<br>> >=20
<br>> > have
<br>> >=20
<br>> > > > experience with (gcc, icl, msvc) this only works wh=
en the compiler is
<br>> >=20
<br>> > able
<br>> >=20
<br>> > > > to
<br>> > > > inline the function call.
<br>> > > >=20
<br>> > > > BTW, if anyone wonders if compiler intrinsics help =
here, no they
<br>> >=20
<br>> > don't.
<br>> >=20
<br>> > > > With
<br>> > > >=20
<br>> > > > the code similar to this:
<br>> > > > template< typename T >
<br>> > > > void atomic<T>::store(T val, memory_or=
der order)
<br>> > > > {
<br>> > > > =20
<br>> > > > __atomic_store_n(&m_value, val, o=
rder);
<br>> > > > =20
<br>> > > > }
<br>> > > >=20
<br>> > > > gcc and icl simply fall back to memory_order_seq_cs=
t regardless of the
<br>> > > > specified order if they cannot inline the function.=
This always
<br>> >=20
<br>> > happens in
<br>> >=20
<br>> > > > debug, for instance.
<br>> > > >=20
<br>> > > > What I'm thinking is if we could require some argum=
ent to be constexpr
<br>> >=20
<br>> > and
<br>> >=20
<br>> > > > pass that 'compile-timeness' hint to the function b=
ody, the
<br>> >=20
<br>> > implementation
<br>> >=20
<br>> > > > could optimize better. For example:
<br>> > > > template< typename T >
<br>> > > > void atomic<T>::store(T val, constexpr=
memory_order order)
<br>> > > > {
<br>> > > > =20
<br>> > > > switch (order) // order is always con=
stexpr
<br>> > > > {
<br>> > > > =20
<br>> > > > // implementations with differ=
ent memory ordering guarantees
<br>> > > > =20
<br>> > > > }
<br>> > > > =20
<br>> > > > }
<br>> > > >=20
<br>> > > > In this case the switch/case would always be optimi=
zed to a single
<br>> >=20
<br>> > case.
<br>> >=20
<br>> > > > And
<br>> > > > the intrinsic-based version would also work as inte=
nded. Also, if we
<br>> >=20
<br>> > have
<br>> >=20
<br>> > > > a
<br>> > > > non-constexpr overload of this function we would al=
so support calling
<br>> >=20
<br>> > with
<br>> >=20
<br>> > > > a
<br>> > > > runtime value of the memory order (not that it woul=
d be of much use
<br>> > > > though).
<br>> > > >=20
<br>> > > > I understand this would have consequences on the AB=
I because constexpr
<br>> > > > arguments essentiall require to duplicate the funct=
ion body for each
<br>> > > > constant
<br>> > > > argument value. It's not a big problem though becau=
se we already do
<br>> >=20
<br>> > that
<br>> >=20
<br>> > > > for
<br>> > > > non-type template parameters.
<br>> > > >=20
<br>> > > > Opinions?
<br>
<br></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_300_7672864.1428852891915--
------=_Part_299_1292937151.1428852891915--
.
Author: Alexander Marinov <sasho648@mail.bg>
Date: Sun, 12 Apr 2015 08:39:31 -0700 (PDT)
Raw View
------=_Part_1192_1663616761.1428853171420
Content-Type: multipart/alternative;
boundary="----=_Part_1193_169818187.1428853171420"
------=_Part_1193_169818187.1428853171420
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
This is called design by contract=20
<http://www.codeproject.com/Articles/8293/Design-by-Contract-in-C> and it's=
=20
currently implemented by using the preprocessor in a very nasty way.
Yeah I actually needed 'constexpr' parameters for the exact same reason as=
=20
you. We could also add compiler-time array bound checks to 'std::array' for=
=20
example.
=D0=BD=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F, 12 =D0=B0=D0=BF=D1=80=D0=B8=D0=BB 201=
5 =D0=B3., 18:03:47 UTC+3, Marcelo Zimbres =D0=BD=D0=B0=D0=BF=D0=B8=D1=81=
=D0=B0:
>
> "I wonder if constexpr function arguments would be a useful addition to=
=20
> the=20
> standard."=20
>
> I would like to see this into the standard. My motivation is that I would=
=20
> like=20
> to detect at compile time, whether the allocate member function of some=
=20
> allocator is used with n different than one 1. For example, say I have:=
=20
>
> std::list<int, my::allocator<int>> foo;=20
>
> I would like to raise a compiler error (or take appropriate action)=20
> if my::allocator<int>::allocate(n) is used with n !=3D 1 inside std::list=
..=20
>
> my::allocator<int>::allocate(1) // This is fine.=20
> my::allocator<int>::allocate(2) // Should be detected at compile time.=20
> my::allocator<int>::allocate(n) // Runtime value should be also detected.=
=20
>
> I think your proposal would allow me to do this.=20
>
> Marcelo=20
>
> 2015-04-12 11:38 GMT-03:00 <inkwizyt...@gmail.com <javascript:>>:=20
> > Then why don't use template parameters?=20
> > template< typename T, memory_order order >=20
> > void atomic<T>::store(T val)=20
> > {=20
> > switch (order)=20
> > {=20
> > // implementations with different memory ordering guarantees=20
> > }=20
> > }=20
> > or if `memory_order` can be group of values with different type:=20
> > template< typename T, typename memory_order_t >=20
> > void atomic<T>::store(T val, memory_order_t order)=20
> > {=20
> > switch (memory_order_t::value)=20
> > {=20
> > // implementations with different memory ordering guarantees=20
> > }=20
> > }=20
> >=20
> >=20
> >=20
> > On Sunday, April 12, 2015 at 2:29:21 PM UTC+2, Andrey Semashev wrote:=
=20
> >>=20
> >> On Sunday 12 April 2015 05:09:29 Alexander Marinov wrote:=20
> >> > I already sketched the details of this idea. You can read it here=20
> >> >=20
> >> > <
> https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/RTss7U=
yl=20
> >> > zgQ>. Only someone needs to write a proposal and/or implement it as =
a=20
> >> > demo=20
> >> > in some open-source compiler (GCC or Clang).=20
> >>=20
> >> No, I don't think your proposal is related to my idea. I'm not trying=
=20
> to=20
> >> make=20
> >> a function constexpr, I'm trying to propagate compile-time nature of=
=20
> some=20
> >> of=20
> >> its arguments to its body, which is executed in run time.=20
> >>=20
> >> (offtopic: And I do think that inline and constexpr are different=20
> >> properties=20
> >> of the code, even though they are somewhat related on the=20
> implementation=20
> >> side;=20
> >> I do not think they should be mixed together in a single keyword.)=20
> >>=20
> >> > =D0=BD=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F, 12 =D0=B0=D0=BF=D1=80=D0=B8=D0=
=BB 2015 =D0=B3., 13:33:17 UTC+3, Andrey Semashev =D0=BD=D0=B0=D0=BF=D0=B8=
=D1=81=D0=B0:=20
> >> > > Hi,=20
> >> > >=20
> >> > > I wonder if constexpr function arguments would be a useful additio=
n=20
> to=20
> >> > > the=20
> >> > >=20
> >> > > standard. Consider this part of std::atomic interface:=20
> >> > > template< typename T >=20
> >> > > void atomic<T>::store(T val, memory_order order)=20
> >> > > {=20
> >> > >=20
> >> > > switch (order)=20
> >> > > {=20
> >> > >=20
> >> > > // implementations with different memory ordering guarantees=
=20
> >> > >=20
> >> > > }=20
> >> > >=20
> >> > > }=20
> >> > >=20
> >> > > The function itself is not constexpr because the implementation ha=
s=20
> a=20
> >> > > runtime=20
> >> > > side effect. However the memory order argument is always constant=
=20
> in=20
> >> > > normal=20
> >> > > uses and the implementation could have had benefitted from knowing=
=20
> >> > > this=20
> >> > > constant at compile time. The current standard does not offer mean=
s=20
> >> > > for=20
> >> > > that,=20
> >> > > so you're out of luck if the compiler is not smart enough to=20
> propagate=20
> >> > > this=20
> >> > > constexpr hint behind the scenes. For the most part with compilers=
=20
> I=20
> >> > > have=20
> >> > > experience with (gcc, icl, msvc) this only works when the compiler=
=20
> is=20
> >> > > able=20
> >> > > to=20
> >> > > inline the function call.=20
> >> > >=20
> >> > > BTW, if anyone wonders if compiler intrinsics help here, no they=
=20
> >> > > don't.=20
> >> > > With=20
> >> > >=20
> >> > > the code similar to this:=20
> >> > > template< typename T >=20
> >> > > void atomic<T>::store(T val, memory_order order)=20
> >> > > {=20
> >> > >=20
> >> > > __atomic_store_n(&m_value, val, order);=20
> >> > >=20
> >> > > }=20
> >> > >=20
> >> > > gcc and icl simply fall back to memory_order_seq_cst regardless of=
=20
> the=20
> >> > > specified order if they cannot inline the function. This always=20
> >> > > happens in=20
> >> > > debug, for instance.=20
> >> > >=20
> >> > > What I'm thinking is if we could require some argument to be=20
> constexpr=20
> >> > > and=20
> >> > > pass that 'compile-timeness' hint to the function body, the=20
> >> > > implementation=20
> >> > >=20
> >> > > could optimize better. For example:=20
> >> > > template< typename T >=20
> >> > > void atomic<T>::store(T val, constexpr memory_order order)=20
> >> > > {=20
> >> > >=20
> >> > > switch (order) // order is always constexpr=20
> >> > > {=20
> >> > >=20
> >> > > // implementations with different memory ordering guarantees=
=20
> >> > >=20
> >> > > }=20
> >> > >=20
> >> > > }=20
> >> > >=20
> >> > > In this case the switch/case would always be optimized to a single=
=20
> >> > > case.=20
> >> > > And=20
> >> > > the intrinsic-based version would also work as intended. Also, if=
=20
> we=20
> >> > > have=20
> >> > > a=20
> >> > > non-constexpr overload of this function we would also support=20
> calling=20
> >> > > with=20
> >> > > a=20
> >> > > runtime value of the memory order (not that it would be of much us=
e=20
> >> > > though).=20
> >> > >=20
> >> > > I understand this would have consequences on the ABI because=20
> constexpr=20
> >> > > arguments essentiall require to duplicate the function body for=20
> each=20
> >> > > constant=20
> >> > > argument value. It's not a big problem though because we already d=
o=20
> >> > > that=20
> >> > > for=20
> >> > > non-type template parameters.=20
> >> > >=20
> >> > > Opinions?=20
> >>=20
> > --=20
> >=20
> > ---=20
> > You received this message because you are subscribed to the Google=20
> Groups=20
> > "ISO C++ Standard - Future Proposals" group.=20
> > To unsubscribe from this group and stop receiving emails from it, send=
=20
> an=20
> > email to std-proposal...@isocpp.org <javascript:>.=20
> > To post to this group, send email to std-pr...@isocpp.org <javascript:>=
..=20
>
> > Visit this group at=20
> > http://groups.google.com/a/isocpp.org/group/std-proposals/.=20
>
--=20
---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_1193_169818187.1428853171420
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">This is called <a href=3D"http://www.codeproject.com/Artic=
les/8293/Design-by-Contract-in-C">design by contract</a> and it's currently=
implemented by using the preprocessor in a very nasty way.<div><br></div><=
div>Yeah I actually needed 'constexpr' parameters for the exact same reason=
as you. We could also add compiler-time array bound checks to 'std::array'=
for example.<br><br>=D0=BD=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F, 12 =D0=B0=D0=BF=
=D1=80=D0=B8=D0=BB 2015 =D0=B3., 18:03:47 UTC+3, Marcelo Zimbres =D0=BD=D0=
=B0=D0=BF=D0=B8=D1=81=D0=B0:<blockquote class=3D"gmail_quote" style=3D"marg=
in: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">"I=
wonder if constexpr function arguments would be a useful addition to the
<br>standard."
<br>
<br>I would like to see this into the standard. My motivation is that I wou=
ld like
<br>to detect at compile time, whether the allocate member function of some
<br>allocator is used with n different than one 1. For example, say I have:
<br>
<br>std::list<int, my::allocator<int>> foo;
<br>
<br>I would like to raise a compiler error (or take appropriate action)
<br>if my::allocator<int>::allocate(<wbr>n) is used with n !=3D 1 ins=
ide std::list.
<br>
<br>my::allocator<int>::allocate(<wbr>1) // This is fine.
<br>my::allocator<int>::allocate(<wbr>2) // Should be detected at com=
pile time.
<br>my::allocator<int>::allocate(<wbr>n) // Runtime value should be a=
lso detected.
<br>
<br>I think your proposal would allow me to do this.
<br>
<br>Marcelo
<br>
<br>2015-04-12 11:38 GMT-03:00 <<a href=3D"javascript:" target=3D"=
_blank" gdf-obfuscated-mailto=3D"OM9n3bKZ-CcJ" rel=3D"nofollow" onmousedown=
=3D"this.href=3D'javascript:';return true;" onclick=3D"this.href=3D'javascr=
ipt:';return true;">inkwizyt...@gmail.com</a>>:
<br>> Then why don't use template parameters?
<br>> template< typename T, memory_order order >
<br>> void atomic<T>::store(T val)
<br>> {
<br>> switch (order)
<br>> {
<br>> // implementations with different memo=
ry ordering guarantees
<br>> }
<br>> }
<br>> or if `memory_order` can be group of values with different type:
<br>> template< typename T, typename memory_order_t >
<br>> void atomic<T>::store(T val, memory_order_t order)
<br>> {
<br>> switch (memory_order_t::value)
<br>> {
<br>> // implementations with different memo=
ry ordering guarantees
<br>> }
<br>> }
<br>>
<br>>
<br>>
<br>> On Sunday, April 12, 2015 at 2:29:21 PM UTC+2, Andrey Semashev wro=
te:
<br>>>
<br>>> On Sunday 12 April 2015 05:09:29 Alexander Marinov wrote:
<br>>> > I already sketched the details of this idea. You can read=
it here
<br>>> >
<br>>> > <<a href=3D"https://groups.google.com/a/isocpp.org/for=
um/#!topic/std-proposals/RTss7Uyl" target=3D"_blank" rel=3D"nofollow" onmou=
sedown=3D"this.href=3D'https://groups.google.com/a/isocpp.org/forum/#!topic=
/std-proposals/RTss7Uyl';return true;" onclick=3D"this.href=3D'https://grou=
ps.google.com/a/isocpp.org/forum/#!topic/std-proposals/RTss7Uyl';return tru=
e;">https://groups.google.com/a/<wbr>isocpp.org/forum/#!topic/std-<wbr>prop=
osals/RTss7Uyl</a>
<br>>> > zgQ>. Only someone needs to write a proposal and/or im=
plement it as a
<br>>> > demo
<br>>> > in some open-source compiler (GCC or Clang).
<br>>>
<br>>> No, I don't think your proposal is related to my idea. I'm not=
trying to
<br>>> make
<br>>> a function constexpr, I'm trying to propagate compile-time nat=
ure of some
<br>>> of
<br>>> its arguments to its body, which is executed in run time.
<br>>>
<br>>> (offtopic: And I do think that inline and constexpr are differ=
ent
<br>>> properties
<br>>> of the code, even though they are somewhat related on the impl=
ementation
<br>>> side;
<br>>> I do not think they should be mixed together in a single keywo=
rd.)
<br>>>
<br>>> > =D0=BD=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F, 12 =D0=B0=D0=BF=D1=
=80=D0=B8=D0=BB 2015 =D0=B3., 13:33:17 UTC+3, Andrey Semashev =D0=BD=D0=B0=
=D0=BF=D0=B8=D1=81=D0=B0:
<br>>> > > Hi,
<br>>> > >
<br>>> > > I wonder if constexpr function arguments would be a =
useful addition to
<br>>> > > the
<br>>> > >
<br>>> > > standard. Consider this part of std::atomic interfac=
e:
<br>>> > > template< typename T >
<br>>> > > void atomic<T>::store(T val, memory_ord=
er order)
<br>>> > > {
<br>>> > >
<br>>> > > switch (order)
<br>>> > > {
<br>>> > >
<br>>> > > // implementations with differe=
nt memory ordering guarantees
<br>>> > >
<br>>> > > }
<br>>> > >
<br>>> > > }
<br>>> > >
<br>>> > > The function itself is not constexpr because the imp=
lementation has a
<br>>> > > runtime
<br>>> > > side effect. However the memory order argument is al=
ways constant in
<br>>> > > normal
<br>>> > > uses and the implementation could have had benefitte=
d from knowing
<br>>> > > this
<br>>> > > constant at compile time. The current standard does =
not offer means
<br>>> > > for
<br>>> > > that,
<br>>> > > so you're out of luck if the compiler is not smart e=
nough to propagate
<br>>> > > this
<br>>> > > constexpr hint behind the scenes. For the most part =
with compilers I
<br>>> > > have
<br>>> > > experience with (gcc, icl, msvc) this only works whe=
n the compiler is
<br>>> > > able
<br>>> > > to
<br>>> > > inline the function call.
<br>>> > >
<br>>> > > BTW, if anyone wonders if compiler intrinsics help h=
ere, no they
<br>>> > > don't.
<br>>> > > With
<br>>> > >
<br>>> > > the code similar to this:
<br>>> > > template< typename T >
<br>>> > > void atomic<T>::store(T val, memory_ord=
er order)
<br>>> > > {
<br>>> > >
<br>>> > > __atomic_store_n(&m_value, val, or=
der);
<br>>> > >
<br>>> > > }
<br>>> > >
<br>>> > > gcc and icl simply fall back to memory_order_seq_cst=
regardless of the
<br>>> > > specified order if they cannot inline the function. =
This always
<br>>> > > happens in
<br>>> > > debug, for instance.
<br>>> > >
<br>>> > > What I'm thinking is if we could require some argume=
nt to be constexpr
<br>>> > > and
<br>>> > > pass that 'compile-timeness' hint to the function bo=
dy, the
<br>>> > > implementation
<br>>> > >
<br>>> > > could optimize better. For example:
<br>>> > > template< typename T >
<br>>> > > void atomic<T>::store(T val, constexpr =
memory_order order)
<br>>> > > {
<br>>> > >
<br>>> > > switch (order) // order is always cons=
texpr
<br>>> > > {
<br>>> > >
<br>>> > > // implementations with differe=
nt memory ordering guarantees
<br>>> > >
<br>>> > > }
<br>>> > >
<br>>> > > }
<br>>> > >
<br>>> > > In this case the switch/case would always be optimiz=
ed to a single
<br>>> > > case.
<br>>> > > And
<br>>> > > the intrinsic-based version would also work as inten=
ded. Also, if we
<br>>> > > have
<br>>> > > a
<br>>> > > non-constexpr overload of this function we would als=
o support calling
<br>>> > > with
<br>>> > > a
<br>>> > > runtime value of the memory order (not that it would=
be of much use
<br>>> > > though).
<br>>> > >
<br>>> > > I understand this would have consequences on the ABI=
because constexpr
<br>>> > > arguments essentiall require to duplicate the functi=
on body for each
<br>>> > > constant
<br>>> > > argument value. It's not a big problem though becaus=
e we already do
<br>>> > > that
<br>>> > > for
<br>>> > > non-type template parameters.
<br>>> > >
<br>>> > > Opinions?
<br>>>
<br>> --
<br>>
<br>> ---
<br>> You received this message because you are subscribed to the Google=
Groups
<br>> "ISO C++ Standard - Future Proposals" group.
<br>> To unsubscribe from this group and stop receiving emails from it, =
send an
<br>> email to <a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-=
mailto=3D"OM9n3bKZ-CcJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javasc=
ript:';return true;" onclick=3D"this.href=3D'javascript:';return true;">std=
-proposal...@<wbr>isocpp.org</a>.
<br>> To post to this group, send email to <a href=3D"javascript:" targe=
t=3D"_blank" gdf-obfuscated-mailto=3D"OM9n3bKZ-CcJ" rel=3D"nofollow" onmous=
edown=3D"this.href=3D'javascript:';return true;" onclick=3D"this.href=3D'ja=
vascript:';return true;">std-pr...@isocpp.org</a>.
<br>> Visit this group at
<br>> <a href=3D"http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://=
groups.google.com/a/isocpp.org/group/std-proposals/';return true;" onclick=
=3D"this.href=3D'http://groups.google.com/a/isocpp.org/group/std-proposals/=
';return true;">http://groups.google.com/a/<wbr>isocpp.org/group/std-<wbr>p=
roposals/</a>.
<br></blockquote></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1193_169818187.1428853171420--
------=_Part_1192_1663616761.1428853171420--
.
Author: Louis Dionne <ldionne.2@gmail.com>
Date: Sun, 12 Apr 2015 15:41:35 -0700 (PDT)
Raw View
------=_Part_339_1522689241.1428878495946
Content-Type: multipart/alternative;
boundary="----=_Part_340_275452188.1428878495946"
------=_Part_340_275452188.1428878495946
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
In the same vein as what has been suggested before, couldn't you use
template parameters to achieve this?
---------------------------------------------------------------------------=
---
#include <atomic>
#include <iostream>
template <std::memory_order order>
using memory_order_c =3D std::integral_constant<std::memory_order, order>;
constexpr memory_order_c<std::memory_order_relaxed>=20
memory_order_relaxed_c{};
// etc...
template <typename T, std::memory_order order>
void store(T val, memory_order_c<order>) {
std::cout << "compile-time argument" << std::endl;
}
template <typename T>
void store(T val, std::memory_order order) {
std::cout << "runtime argument" << std::endl;
}
int main() {
store(1, memory_order_relaxed_c);
store(1, std::memory_order_relaxed);
}
---------------------------------------------------------------------------=
---
Basically, you would use `memory_order_relaxed_c` to convey the fact that
the information is known at compile-time, and `std::memory_order_relaxed`
otherwise. Using `integral_constant` objects instead of raw non-type=20
template parameters has the advantage of keeping a unified function call
syntax.
Also, this approach makes it possible to have different implementations=20
that would otherwise fail to compile for different values of `order` by=20
overloading the `store` functioon. It is unclear to me how this might=20
be achieved with `constexpr` parameters, but I admit I haven't read the=20
papers referrenced in previous posts.
Regards,
Louis
On Sunday, 12 April 2015 11:39:31 UTC-4, Alexander Marinov wrote:
>
> This is called design by contract=20
> <http://www.codeproject.com/Articles/8293/Design-by-Contract-in-C> and=20
> it's currently implemented by using the preprocessor in a very nasty way.
>
> Yeah I actually needed 'constexpr' parameters for the exact same reason a=
s=20
> you. We could also add compiler-time array bound checks to 'std::array' f=
or=20
> example.
>
> =D0=BD=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F, 12 =D0=B0=D0=BF=D1=80=D0=B8=D0=BB 2=
015 =D0=B3., 18:03:47 UTC+3, Marcelo Zimbres =D0=BD=D0=B0=D0=BF=D0=B8=D1=81=
=D0=B0:
>>
>> "I wonder if constexpr function arguments would be a useful addition to=
=20
>> the=20
>> standard."=20
>>
>> I would like to see this into the standard. My motivation is that I woul=
d=20
>> like=20
>> to detect at compile time, whether the allocate member function of some=
=20
>> allocator is used with n different than one 1. For example, say I have:=
=20
>>
>> std::list<int, my::allocator<int>> foo;=20
>>
>> I would like to raise a compiler error (or take appropriate action)=20
>> if my::allocator<int>::allocate(n) is used with n !=3D 1 inside std::lis=
t.=20
>>
>> my::allocator<int>::allocate(1) // This is fine.=20
>> my::allocator<int>::allocate(2) // Should be detected at compile time.=
=20
>> my::allocator<int>::allocate(n) // Runtime value should be also detected=
..=20
>>
>> I think your proposal would allow me to do this.=20
>>
>> Marcelo=20
>>
>> 2015-04-12 11:38 GMT-03:00 <inkwizyt...@gmail.com>:=20
>> > Then why don't use template parameters?=20
>> > template< typename T, memory_order order >=20
>> > void atomic<T>::store(T val)=20
>> > {=20
>> > switch (order)=20
>> > {=20
>> > // implementations with different memory ordering guarantees=
=20
>> > }=20
>> > }=20
>> > or if `memory_order` can be group of values with different type:=20
>> > template< typename T, typename memory_order_t >=20
>> > void atomic<T>::store(T val, memory_order_t order)=20
>> > {=20
>> > switch (memory_order_t::value)=20
>> > {=20
>> > // implementations with different memory ordering guarantees=
=20
>> > }=20
>> > }=20
>> >=20
>> >=20
>> >=20
>> > On Sunday, April 12, 2015 at 2:29:21 PM UTC+2, Andrey Semashev wrote:=
=20
>> >>=20
>> >> On Sunday 12 April 2015 05:09:29 Alexander Marinov wrote:=20
>> >> > I already sketched the details of this idea. You can read it here=
=20
>> >> >=20
>> >> > <
>> https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/RTss7=
Uyl=20
>> >> > zgQ>. Only someone needs to write a proposal and/or implement it as=
=20
>> a=20
>> >> > demo=20
>> >> > in some open-source compiler (GCC or Clang).=20
>> >>=20
>> >> No, I don't think your proposal is related to my idea. I'm not trying=
=20
>> to=20
>> >> make=20
>> >> a function constexpr, I'm trying to propagate compile-time nature of=
=20
>> some=20
>> >> of=20
>> >> its arguments to its body, which is executed in run time.=20
>> >>=20
>> >> (offtopic: And I do think that inline and constexpr are different=20
>> >> properties=20
>> >> of the code, even though they are somewhat related on the=20
>> implementation=20
>> >> side;=20
>> >> I do not think they should be mixed together in a single keyword.)=20
>> >>=20
>> >> > =D0=BD=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F, 12 =D0=B0=D0=BF=D1=80=D0=B8=
=D0=BB 2015 =D0=B3., 13:33:17 UTC+3, Andrey Semashev =D0=BD=D0=B0=D0=BF=D0=
=B8=D1=81=D0=B0:=20
>> >> > > Hi,=20
>> >> > >=20
>> >> > > I wonder if constexpr function arguments would be a useful=20
>> addition to=20
>> >> > > the=20
>> >> > >=20
>> >> > > standard. Consider this part of std::atomic interface:=20
>> >> > > template< typename T >=20
>> >> > > void atomic<T>::store(T val, memory_order order)=20
>> >> > > {=20
>> >> > >=20
>> >> > > switch (order)=20
>> >> > > {=20
>> >> > >=20
>> >> > > // implementations with different memory ordering guarantee=
s=20
>> >> > >=20
>> >> > > }=20
>> >> > >=20
>> >> > > }=20
>> >> > >=20
>> >> > > The function itself is not constexpr because the implementation=
=20
>> has a=20
>> >> > > runtime=20
>> >> > > side effect. However the memory order argument is always constant=
=20
>> in=20
>> >> > > normal=20
>> >> > > uses and the implementation could have had benefitted from knowin=
g=20
>> >> > > this=20
>> >> > > constant at compile time. The current standard does not offer=20
>> means=20
>> >> > > for=20
>> >> > > that,=20
>> >> > > so you're out of luck if the compiler is not smart enough to=20
>> propagate=20
>> >> > > this=20
>> >> > > constexpr hint behind the scenes. For the most part with compiler=
s=20
>> I=20
>> >> > > have=20
>> >> > > experience with (gcc, icl, msvc) this only works when the compile=
r=20
>> is=20
>> >> > > able=20
>> >> > > to=20
>> >> > > inline the function call.=20
>> >> > >=20
>> >> > > BTW, if anyone wonders if compiler intrinsics help here, no they=
=20
>> >> > > don't.=20
>> >> > > With=20
>> >> > >=20
>> >> > > the code similar to this:=20
>> >> > > template< typename T >=20
>> >> > > void atomic<T>::store(T val, memory_order order)=20
>> >> > > {=20
>> >> > >=20
>> >> > > __atomic_store_n(&m_value, val, order);=20
>> >> > >=20
>> >> > > }=20
>> >> > >=20
>> >> > > gcc and icl simply fall back to memory_order_seq_cst regardless o=
f=20
>> the=20
>> >> > > specified order if they cannot inline the function. This always=
=20
>> >> > > happens in=20
>> >> > > debug, for instance.=20
>> >> > >=20
>> >> > > What I'm thinking is if we could require some argument to be=20
>> constexpr=20
>> >> > > and=20
>> >> > > pass that 'compile-timeness' hint to the function body, the=20
>> >> > > implementation=20
>> >> > >=20
>> >> > > could optimize better. For example:=20
>> >> > > template< typename T >=20
>> >> > > void atomic<T>::store(T val, constexpr memory_order order)=20
>> >> > > {=20
>> >> > >=20
>> >> > > switch (order) // order is always constexpr=20
>> >> > > {=20
>> >> > >=20
>> >> > > // implementations with different memory ordering guarantee=
s=20
>> >> > >=20
>> >> > > }=20
>> >> > >=20
>> >> > > }=20
>> >> > >=20
>> >> > > In this case the switch/case would always be optimized to a singl=
e=20
>> >> > > case.=20
>> >> > > And=20
>> >> > > the intrinsic-based version would also work as intended. Also, if=
=20
>> we=20
>> >> > > have=20
>> >> > > a=20
>> >> > > non-constexpr overload of this function we would also support=20
>> calling=20
>> >> > > with=20
>> >> > > a=20
>> >> > > runtime value of the memory order (not that it would be of much=
=20
>> use=20
>> >> > > though).=20
>> >> > >=20
>> >> > > I understand this would have consequences on the ABI because=20
>> constexpr=20
>> >> > > arguments essentiall require to duplicate the function body for=
=20
>> each=20
>> >> > > constant=20
>> >> > > argument value. It's not a big problem though because we already=
=20
>> do=20
>> >> > > that=20
>> >> > > for=20
>> >> > > non-type template parameters.=20
>> >> > >=20
>> >> > > Opinions?=20
>> >>=20
>> > --=20
>> >=20
>> > ---=20
>> > You received this message because you are subscribed to the Google=20
>> Groups=20
>> > "ISO C++ Standard - Future Proposals" group.=20
>> > To unsubscribe from this group and stop receiving emails from it, send=
=20
>> an=20
>> > email to std-proposal...@isocpp.org.=20
>> > To post to this group, send email to std-pr...@isocpp.org.=20
>> > Visit this group at=20
>> > http://groups.google.com/a/isocpp.org/group/std-proposals/.=20
>>
>
--=20
---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_340_275452188.1428878495946
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div><div><br></div><div>In the same vein as what has been=
suggested before, couldn't you use</div><div>template parameters to achiev=
e this?</div><div><br></div><div>------------------------------------------=
------------------------------------</div><div>#include <atomic></div=
><div>#include <iostream></div><div><br></div><div>template <std::=
memory_order order></div><div>using memory_order_c =3D std::integral_con=
stant<std::memory_order, order>;</div><div><br></div><div>constexpr m=
emory_order_c<std::memory_order_relaxed> memory_order_relaxed_c{};</d=
iv><div>// etc...</div><div><br></div><div><br></div><div>template <type=
name T, std::memory_order order></div><div>void store(T val, memory_orde=
r_c<order>) {</div><div> std::cout << "compile-tim=
e argument" << std::endl;</div><div>}</div><div><br></div><div>templa=
te <typename T></div><div>void store(T val, std::memory_order order) =
{</div><div> std::cout << "runtime argument" << st=
d::endl;</div><div>}</div><div><br></div><div><br></div><div>int main() {</=
div><div> store(1, memory_order_relaxed_c);</div><div> &=
nbsp; store(1, std::memory_order_relaxed);</div><div>}</div><div>----------=
--------------------------------------------------------------------</div><=
div><br></div><div>Basically, you would use `memory_order_relaxed_c` to con=
vey the fact that</div><div>the information is known at compile-time, and `=
std::memory_order_relaxed`</div><div>otherwise. Using `integral_constant` o=
bjects instead of raw non-type </div><div>template parameters has the =
advantage of keeping a unified function call</div><div>syntax.</div><div><b=
r></div><div>Also, this approach makes it possible to have different implem=
entations </div><div>that would otherwise fail to compile for differen=
t values of `order` by </div><div>overloading the `store` functioon. I=
t is unclear to me how this might </div><div>be achieved with `constex=
pr` parameters, but I admit I haven't read the </div><div>papers refer=
renced in previous posts.</div></div><div><br></div><div>Regards,</div><div=
>Louis</div><br>On Sunday, 12 April 2015 11:39:31 UTC-4, Alexander Marinov =
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">This i=
s called <a href=3D"http://www.codeproject.com/Articles/8293/Design-by-Cont=
ract-in-C" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'h=
ttp://www.google.com/url?q\75http%3A%2F%2Fwww.codeproject.com%2FArticles%2F=
8293%2FDesign-by-Contract-in-C\46sa\75D\46sntz\0751\46usg\75AFQjCNHuMddig2g=
jStBDqq6-0EIq_9o8JQ';return true;" onclick=3D"this.href=3D'http://www.googl=
e.com/url?q\75http%3A%2F%2Fwww.codeproject.com%2FArticles%2F8293%2FDesign-b=
y-Contract-in-C\46sa\75D\46sntz\0751\46usg\75AFQjCNHuMddig2gjStBDqq6-0EIq_9=
o8JQ';return true;">design by contract</a> and it's currently implemented b=
y using the preprocessor in a very nasty way.<div><br></div><div>Yeah I act=
ually needed 'constexpr' parameters for the exact same reason as you. We co=
uld also add compiler-time array bound checks to 'std::array' for example.<=
br><br>=D0=BD=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F, 12 =D0=B0=D0=BF=D1=80=D0=B8=D0=
=BB 2015 =D0=B3., 18:03:47 UTC+3, Marcelo Zimbres =D0=BD=D0=B0=D0=BF=D0=B8=
=D1=81=D0=B0:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-lef=
t:0.8ex;border-left:1px #ccc solid;padding-left:1ex">"I wonder if constexpr=
function arguments would be a useful addition to the
<br>standard."
<br>
<br>I would like to see this into the standard. My motivation is that I wou=
ld like
<br>to detect at compile time, whether the allocate member function of some
<br>allocator is used with n different than one 1. For example, say I have:
<br>
<br>std::list<int, my::allocator<int>> foo;
<br>
<br>I would like to raise a compiler error (or take appropriate action)
<br>if my::allocator<int>::allocate(<wbr>n) is used with n !=3D 1 ins=
ide std::list.
<br>
<br>my::allocator<int>::allocate(<wbr>1) // This is fine.
<br>my::allocator<int>::allocate(<wbr>2) // Should be detected at com=
pile time.
<br>my::allocator<int>::allocate(<wbr>n) // Runtime value should be a=
lso detected.
<br>
<br>I think your proposal would allow me to do this.
<br>
<br>Marcelo
<br>
<br>2015-04-12 11:38 GMT-03:00 <<a rel=3D"nofollow">inkwizyt...@gm=
ail.com</a>>:
<br>> Then why don't use template parameters?
<br>> template< typename T, memory_order order >
<br>> void atomic<T>::store(T val)
<br>> {
<br>> switch (order)
<br>> {
<br>> // implementations with different memo=
ry ordering guarantees
<br>> }
<br>> }
<br>> or if `memory_order` can be group of values with different type:
<br>> template< typename T, typename memory_order_t >
<br>> void atomic<T>::store(T val, memory_order_t order)
<br>> {
<br>> switch (memory_order_t::value)
<br>> {
<br>> // implementations with different memo=
ry ordering guarantees
<br>> }
<br>> }
<br>>
<br>>
<br>>
<br>> On Sunday, April 12, 2015 at 2:29:21 PM UTC+2, Andrey Semashev wro=
te:
<br>>>
<br>>> On Sunday 12 April 2015 05:09:29 Alexander Marinov wrote:
<br>>> > I already sketched the details of this idea. You can read=
it here
<br>>> >
<br>>> > <<a href=3D"https://groups.google.com/a/isocpp.org/for=
um/#!topic/std-proposals/RTss7Uyl" rel=3D"nofollow" target=3D"_blank" onmou=
sedown=3D"this.href=3D'https://groups.google.com/a/isocpp.org/forum/#!topic=
/std-proposals/RTss7Uyl';return true;" onclick=3D"this.href=3D'https://grou=
ps.google.com/a/isocpp.org/forum/#!topic/std-proposals/RTss7Uyl';return tru=
e;">https://groups.google.com/a/<wbr>isocpp.org/forum/#!topic/std-<wbr>prop=
osals/RTss7Uyl</a>
<br>>> > zgQ>. Only someone needs to write a proposal and/or im=
plement it as a
<br>>> > demo
<br>>> > in some open-source compiler (GCC or Clang).
<br>>>
<br>>> No, I don't think your proposal is related to my idea. I'm not=
trying to
<br>>> make
<br>>> a function constexpr, I'm trying to propagate compile-time nat=
ure of some
<br>>> of
<br>>> its arguments to its body, which is executed in run time.
<br>>>
<br>>> (offtopic: And I do think that inline and constexpr are differ=
ent
<br>>> properties
<br>>> of the code, even though they are somewhat related on the impl=
ementation
<br>>> side;
<br>>> I do not think they should be mixed together in a single keywo=
rd.)
<br>>>
<br>>> > =D0=BD=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F, 12 =D0=B0=D0=BF=D1=
=80=D0=B8=D0=BB 2015 =D0=B3., 13:33:17 UTC+3, Andrey Semashev =D0=BD=D0=B0=
=D0=BF=D0=B8=D1=81=D0=B0:
<br>>> > > Hi,
<br>>> > >
<br>>> > > I wonder if constexpr function arguments would be a =
useful addition to
<br>>> > > the
<br>>> > >
<br>>> > > standard. Consider this part of std::atomic interfac=
e:
<br>>> > > template< typename T >
<br>>> > > void atomic<T>::store(T val, memory_ord=
er order)
<br>>> > > {
<br>>> > >
<br>>> > > switch (order)
<br>>> > > {
<br>>> > >
<br>>> > > // implementations with differe=
nt memory ordering guarantees
<br>>> > >
<br>>> > > }
<br>>> > >
<br>>> > > }
<br>>> > >
<br>>> > > The function itself is not constexpr because the imp=
lementation has a
<br>>> > > runtime
<br>>> > > side effect. However the memory order argument is al=
ways constant in
<br>>> > > normal
<br>>> > > uses and the implementation could have had benefitte=
d from knowing
<br>>> > > this
<br>>> > > constant at compile time. The current standard does =
not offer means
<br>>> > > for
<br>>> > > that,
<br>>> > > so you're out of luck if the compiler is not smart e=
nough to propagate
<br>>> > > this
<br>>> > > constexpr hint behind the scenes. For the most part =
with compilers I
<br>>> > > have
<br>>> > > experience with (gcc, icl, msvc) this only works whe=
n the compiler is
<br>>> > > able
<br>>> > > to
<br>>> > > inline the function call.
<br>>> > >
<br>>> > > BTW, if anyone wonders if compiler intrinsics help h=
ere, no they
<br>>> > > don't.
<br>>> > > With
<br>>> > >
<br>>> > > the code similar to this:
<br>>> > > template< typename T >
<br>>> > > void atomic<T>::store(T val, memory_ord=
er order)
<br>>> > > {
<br>>> > >
<br>>> > > __atomic_store_n(&m_value, val, or=
der);
<br>>> > >
<br>>> > > }
<br>>> > >
<br>>> > > gcc and icl simply fall back to memory_order_seq_cst=
regardless of the
<br>>> > > specified order if they cannot inline the function. =
This always
<br>>> > > happens in
<br>>> > > debug, for instance.
<br>>> > >
<br>>> > > What I'm thinking is if we could require some argume=
nt to be constexpr
<br>>> > > and
<br>>> > > pass that 'compile-timeness' hint to the function bo=
dy, the
<br>>> > > implementation
<br>>> > >
<br>>> > > could optimize better. For example:
<br>>> > > template< typename T >
<br>>> > > void atomic<T>::store(T val, constexpr =
memory_order order)
<br>>> > > {
<br>>> > >
<br>>> > > switch (order) // order is always cons=
texpr
<br>>> > > {
<br>>> > >
<br>>> > > // implementations with differe=
nt memory ordering guarantees
<br>>> > >
<br>>> > > }
<br>>> > >
<br>>> > > }
<br>>> > >
<br>>> > > In this case the switch/case would always be optimiz=
ed to a single
<br>>> > > case.
<br>>> > > And
<br>>> > > the intrinsic-based version would also work as inten=
ded. Also, if we
<br>>> > > have
<br>>> > > a
<br>>> > > non-constexpr overload of this function we would als=
o support calling
<br>>> > > with
<br>>> > > a
<br>>> > > runtime value of the memory order (not that it would=
be of much use
<br>>> > > though).
<br>>> > >
<br>>> > > I understand this would have consequences on the ABI=
because constexpr
<br>>> > > arguments essentiall require to duplicate the functi=
on body for each
<br>>> > > constant
<br>>> > > argument value. It's not a big problem though becaus=
e we already do
<br>>> > > that
<br>>> > > for
<br>>> > > non-type template parameters.
<br>>> > >
<br>>> > > Opinions?
<br>>>
<br>> --
<br>>
<br>> ---
<br>> You received this message because you are subscribed to the Google=
Groups
<br>> "ISO C++ Standard - Future Proposals" group.
<br>> To unsubscribe from this group and stop receiving emails from it, =
send an
<br>> email to <a rel=3D"nofollow">std-proposal...@isocpp.org</a>.
<br>> To post to this group, send email to <a rel=3D"nofollow">std-pr...=
@isocpp.org</a>.
<br>> Visit this group at
<br>> <a href=3D"http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/" rel=3D"nofollow" target=3D"_blank" onmousedown=3D"this.href=3D'http://=
groups.google.com/a/isocpp.org/group/std-proposals/';return true;" onclick=
=3D"this.href=3D'http://groups.google.com/a/isocpp.org/group/std-proposals/=
';return true;">http://groups.google.com/a/<wbr>isocpp.org/group/std-<wbr>p=
roposals/</a>.
<br></blockquote></div></div></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_340_275452188.1428878495946--
------=_Part_339_1522689241.1428878495946--
.
Author: Andrey Semashev <andrey.semashev@gmail.com>
Date: Mon, 13 Apr 2015 10:53:53 +0300
Raw View
On Sunday 12 April 2015 15:41:35 Louis Dionne wrote:
> In the same vein as what has been suggested before, couldn't you use
> template parameters to achieve this?
>=20
> -------------------------------------------------------------------------=
---
> -- #include <atomic>
> #include <iostream>
>=20
> template <std::memory_order order>
> using memory_order_c =3D std::integral_constant<std::memory_order, order>=
;
>=20
> constexpr memory_order_c<std::memory_order_relaxed>
> memory_order_relaxed_c{};
> // etc...
>=20
>=20
> template <typename T, std::memory_order order>
> void store(T val, memory_order_c<order>) {
> std::cout << "compile-time argument" << std::endl;
> }
>=20
> template <typename T>
> void store(T val, std::memory_order order) {
> std::cout << "runtime argument" << std::endl;
> }
>=20
>=20
> int main() {
> store(1, memory_order_relaxed_c);
> store(1, std::memory_order_relaxed);
> }
> -------------------------------------------------------------------------=
---
> --
>=20
> Basically, you would use `memory_order_relaxed_c` to convey the fact that
> the information is known at compile-time, and `std::memory_order_relaxed`
> otherwise. Using `integral_constant` objects instead of raw non-type
> template parameters has the advantage of keeping a unified function call
> syntax.
Yes, that is possible, although it would require a change in user's code. T=
he=20
second store in your example would still be interpreted as having a "runtim=
e"=20
argument, which is what I was trying to fix. Also, this approach does not=
=20
scale to support compile time checking of std::array bounds suggested by=20
Alexander.
std::array< int, 10 > arr;
arr[20] =3D 5; // compilation failure: index out of bounds
> Also, this approach makes it possible to have different implementations
> that would otherwise fail to compile for different values of `order` by
> overloading the `store` functioon. It is unclear to me how this might
> be achieved with `constexpr` parameters, but I admit I haven't read the
> papers referrenced in previous posts.
I'm not sure what you mean here, could you clarify?
> On Sunday, 12 April 2015 11:39:31 UTC-4, Alexander Marinov wrote:
> > This is called design by contract
> > <http://www.codeproject.com/Articles/8293/Design-by-Contract-in-C> and
> > it's currently implemented by using the preprocessor in a very nasty wa=
y.
> >=20
> > Yeah I actually needed 'constexpr' parameters for the exact same reason=
as
> > you. We could also add compiler-time array bound checks to 'std::array'
> > for
> > example.
> >=20
> > =D0=BD=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F, 12 =D0=B0=D0=BF=D1=80=D0=B8=D0=BB=
2015 =D0=B3., 18:03:47 UTC+3, Marcelo Zimbres =D0=BD=D0=B0=D0=BF=D0=B8=D1=
=81=D0=B0:
> >> "I wonder if constexpr function arguments would be a useful addition t=
o
> >> the
> >> standard."
> >>=20
> >> I would like to see this into the standard. My motivation is that I wo=
uld
> >> like
> >> to detect at compile time, whether the allocate member function of som=
e
> >> allocator is used with n different than one 1. For example, say I have=
:
> >>=20
> >> std::list<int, my::allocator<int>> foo;
> >>=20
> >> I would like to raise a compiler error (or take appropriate action)
> >> if my::allocator<int>::allocate(n) is used with n !=3D 1 inside std::l=
ist.
> >>=20
> >> my::allocator<int>::allocate(1) // This is fine.
> >> my::allocator<int>::allocate(2) // Should be detected at compile time.
> >> my::allocator<int>::allocate(n) // Runtime value should be also detect=
ed.
> >>=20
> >> I think your proposal would allow me to do this.
> >>=20
> >> Marcelo
> >>=20
> >> 2015-04-12 11:38 GMT-03:00 <inkwizyt...@gmail.com>:
> >> > Then why don't use template parameters?
> >> > template< typename T, memory_order order >
> >> > void atomic<T>::store(T val)
> >> > {
> >> >=20
> >> > switch (order)
> >> > {
> >> > =20
> >> > // implementations with different memory ordering guarantees
> >> > =20
> >> > }
> >> >=20
> >> > }
> >> > or if `memory_order` can be group of values with different type:
> >> > template< typename T, typename memory_order_t >
> >> > void atomic<T>::store(T val, memory_order_t order)
> >> > {
> >> >=20
> >> > switch (memory_order_t::value)
> >> > {
> >> > =20
> >> > // implementations with different memory ordering guarantees
> >> > =20
> >> > }
> >> >=20
> >> > }
> >> >=20
> >> > On Sunday, April 12, 2015 at 2:29:21 PM UTC+2, Andrey Semashev wrote=
:
> >> >> On Sunday 12 April 2015 05:09:29 Alexander Marinov wrote:
> >> >> > I already sketched the details of this idea. You can read it here
> >> >> >=20
> >> >> > <
> >>=20
> >> https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/RTs=
s7U
> >> yl
> >>=20
> >> >> > zgQ>. Only someone needs to write a proposal and/or implement it =
as
> >>=20
> >> a
> >>=20
> >> >> > demo
> >> >> > in some open-source compiler (GCC or Clang).
> >> >>=20
> >> >> No, I don't think your proposal is related to my idea. I'm not tryi=
ng
> >>=20
> >> to
> >>=20
> >> >> make
> >> >> a function constexpr, I'm trying to propagate compile-time nature o=
f
> >>=20
> >> some
> >>=20
> >> >> of
> >> >> its arguments to its body, which is executed in run time.
> >> >>=20
> >> >> (offtopic: And I do think that inline and constexpr are different
> >> >> properties
> >> >> of the code, even though they are somewhat related on the
> >>=20
> >> implementation
> >>=20
> >> >> side;
> >> >> I do not think they should be mixed together in a single keyword.)
> >> >>=20
> >> >> > =D0=BD=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F, 12 =D0=B0=D0=BF=D1=80=D0=B8=
=D0=BB 2015 =D0=B3., 13:33:17 UTC+3, Andrey Semashev =D0=BD=D0=B0=D0=BF=D0=
=B8=D1=81=D0=B0:
> >> >> > > Hi,
> >> >> > >=20
> >> >> > > I wonder if constexpr function arguments would be a useful
> >>=20
> >> addition to
> >>=20
> >> >> > > the
> >> >> > >=20
> >> >> > > standard. Consider this part of std::atomic interface:
> >> >> > > template< typename T >
> >> >> > > void atomic<T>::store(T val, memory_order order)
> >> >> > > {
> >> >> > > =20
> >> >> > > switch (order)
> >> >> > > {
> >> >> > > =20
> >> >> > > // implementations with different memory ordering guarant=
ees
> >> >> > > =20
> >> >> > > }
> >> >> > > =20
> >> >> > > }
> >> >> > >=20
> >> >> > > The function itself is not constexpr because the implementation
> >>=20
> >> has a
> >>=20
> >> >> > > runtime
> >> >> > > side effect. However the memory order argument is always consta=
nt
> >>=20
> >> in
> >>=20
> >> >> > > normal
> >> >> > > uses and the implementation could have had benefitted from know=
ing
> >> >> > > this
> >> >> > > constant at compile time. The current standard does not offer
> >>=20
> >> means
> >>=20
> >> >> > > for
> >> >> > > that,
> >> >> > > so you're out of luck if the compiler is not smart enough to
> >>=20
> >> propagate
> >>=20
> >> >> > > this
> >> >> > > constexpr hint behind the scenes. For the most part with compil=
ers
> >>=20
> >> I
> >>=20
> >> >> > > have
> >> >> > > experience with (gcc, icl, msvc) this only works when the compi=
ler
> >>=20
> >> is
> >>=20
> >> >> > > able
> >> >> > > to
> >> >> > > inline the function call.
> >> >> > >=20
> >> >> > > BTW, if anyone wonders if compiler intrinsics help here, no the=
y
> >> >> > > don't.
> >> >> > > With
> >> >> > >=20
> >> >> > > the code similar to this:
> >> >> > > template< typename T >
> >> >> > > void atomic<T>::store(T val, memory_order order)
> >> >> > > {
> >> >> > > =20
> >> >> > > __atomic_store_n(&m_value, val, order);
> >> >> > > =20
> >> >> > > }
> >> >> > >=20
> >> >> > > gcc and icl simply fall back to memory_order_seq_cst regardless=
of
> >>=20
> >> the
> >>=20
> >> >> > > specified order if they cannot inline the function. This always
> >> >> > > happens in
> >> >> > > debug, for instance.
> >> >> > >=20
> >> >> > > What I'm thinking is if we could require some argument to be
> >>=20
> >> constexpr
> >>=20
> >> >> > > and
> >> >> > > pass that 'compile-timeness' hint to the function body, the
> >> >> > > implementation
> >> >> > >=20
> >> >> > > could optimize better. For example:
> >> >> > > template< typename T >
> >> >> > > void atomic<T>::store(T val, constexpr memory_order order)
> >> >> > > {
> >> >> > > =20
> >> >> > > switch (order) // order is always constexpr
> >> >> > > {
> >> >> > > =20
> >> >> > > // implementations with different memory ordering guarant=
ees
> >> >> > > =20
> >> >> > > }
> >> >> > > =20
> >> >> > > }
> >> >> > >=20
> >> >> > > In this case the switch/case would always be optimized to a sin=
gle
> >> >> > > case.
> >> >> > > And
> >> >> > > the intrinsic-based version would also work as intended. Also, =
if
> >>=20
> >> we
> >>=20
> >> >> > > have
> >> >> > > a
> >> >> > > non-constexpr overload of this function we would also support
> >>=20
> >> calling
> >>=20
> >> >> > > with
> >> >> > > a
> >> >> > > runtime value of the memory order (not that it would be of much
> >>=20
> >> use
> >>=20
> >> >> > > though).
> >> >> > >=20
> >> >> > > I understand this would have consequences on the ABI because
> >>=20
> >> constexpr
> >>=20
> >> >> > > arguments essentiall require to duplicate the function body for
> >>=20
> >> each
> >>=20
> >> >> > > constant
> >> >> > > argument value. It's not a big problem though because we alread=
y
> >>=20
> >> do
> >>=20
> >> >> > > that
> >> >> > > for
> >> >> > > non-type template parameters.
> >> >> > >=20
> >> >> > > Opinions?
> >>=20
> >> Groups
> >>=20
> >> > "ISO C++ Standard - Future Proposals" group.
> >> > To unsubscribe from this group and stop receiving emails from it, se=
nd
> >>=20
> >> an
> >>=20
> >> > email to std-proposal...@isocpp.org.
> >> > To post to this group, send email to std-pr...@isocpp.org.
> >> > Visit this group at
> >> > http://groups.google.com/a/isocpp.org/group/std-proposals/.
--=20
---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Louis Dionne <ldionne.2@gmail.com>
Date: Mon, 13 Apr 2015 05:49:21 -0700 (PDT)
Raw View
------=_Part_67_644489539.1428929361548
Content-Type: multipart/alternative;
boundary="----=_Part_68_28166505.1428929361548"
------=_Part_68_28166505.1428929361548
Content-Type: text/plain; charset=UTF-8
On Monday, 13 April 2015 03:53:59 UTC-4, Andrey Semashev wrote:
> On Sunday 12 April 2015 15:41:35 Louis Dionne wrote:
> >
> > [...]
> >
> > Basically, you would use `memory_order_relaxed_c` to convey the fact
that
> > the information is known at compile-time, and
`std::memory_order_relaxed`
> > otherwise. Using `integral_constant` objects instead of raw non-type
> > template parameters has the advantage of keeping a unified function
call
> > syntax.
>
> Yes, that is possible, although it would require a change in user's code.
The
> second store in your example would still be interpreted as having a
"runtime"
> argument, which is what I was trying to fix.
That is true. What I'm suggesting is to explicitly mark the arguments as
constexpr, while what you are asking for is for the compiler to mark them
as such automatically.
> Also, this approach does not scale to support compile time checking of
> std::array bounds suggested by Alexander.
>
> std::array< int, 10 > arr;
> arr[20] = 5; // compilation failure: index out of bounds
Yes it does. You just have to index the array with a
`std::integral_constant`.
------------------------------------------------------------------------------
#include <array>
#include <cstddef>
#include <type_traits>
constexpr int to_int(char c)
{ return static_cast<int>(c) - 48; }
template <std::size_t N>
constexpr unsigned long parse(const char (&arr)[N]) {
unsigned long number = 0, base = 1;
for (std::size_t i = 0; i < N; ++i) {
number += to_int(arr[N - 1 - i]) * base;
base *= 10;
}
return number;
}
template <char ...c>
constexpr std::integral_constant<unsigned long, parse<sizeof...(c)>({c...})>
operator"" _c() { return {}; }
template <typename T, std::size_t N, typename Index>
constexpr T at(std::array<T, N> array, Index) {
static_assert(Index::value < N, "Array index out of bounds!");
return array[Index::value];
}
int main() {
std::array<int, 3> a{{1, 2, 3}};
at(a, 2_c); // ok
at(a, 3_c); // error: static_assert failed "Array index out of bounds!"
}
------------------------------------------------------------------------------
This `_c` suffix and similar ideas are provided in the Hana library [1].
> > Also, this approach makes it possible to have different implementations
> > that would otherwise fail to compile for different values of `order` by
> > overloading the `store` functioon. It is unclear to me how this might
> > be achieved with `constexpr` parameters, but I admit I haven't read the
> > papers referrenced in previous posts.
>
> I'm not sure what you mean here, could you clarify?
What I mean is that with constexpr parameters, all the branches in the
switch
are required to compile. For example, in the following, if `A()` does not
compile when the memory order is `std::memory_order_consume`, then you will
get a hard error:
template <typename T>
void store(T val, constexpr memory_order order) {
switch (order) {
case std::memory_order_relaxed:
A();
break;
case std::memory_order_consume:
B();
break;
}
}
However, with what I sketched, you could instead have
template <typename T>
void store(T val, memory_order_c<std::memory_order_relaxed>) {
A();
}
template <typename T>
void store(T val, memory_order_c<std::memory_order_consume>) {
B();
}
This way, `A()` does not have to be a valid expression when
`std::memory_order_consume` is sent to `store`, and similarly
for `B()` and `std::memory_order_relaxed`. It is unclear how
this would be of any use in this precise use case, but it is
very important in other settings.
Regards,
Louis
[1]: http://github.com/ldionne/hana
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_68_28166505.1428929361548
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>On Monday, 13 April 2015 03:53:59 UTC-4, Andrey Semas=
hev wrote:</div><div>> On Sunday 12 April 2015 15:41:35 Louis Dionne wro=
te: </div><div>> ></div><div>> > [...]</div><div>> >=
</div><div>> > Basically, you would use `memory_order_relaxed_c=
` to convey the fact that </div><div>> > the information is know=
n at compile-time, and `std::memory_order_relaxed` </div><div>> >=
; otherwise. Using `integral_constant` objects instead of raw non-type =
;</div><div>> > template parameters has the advantage of keeping a un=
ified function call </div><div>> > syntax. </div><div>>&=
nbsp;</div><div>> Yes, that is possible, although it would require a cha=
nge in user's code. The </div><div>> second store in your example w=
ould still be interpreted as having a "runtime" </div><div>> argume=
nt, which is what I was trying to fix. </div><div><br></div><div>That =
is true. What I'm suggesting is to explicitly mark the arguments as</div><d=
iv>constexpr, while what you are asking for is for the compiler to mark the=
m</div><div>as such automatically.</div><div><br></div><div>> Also, this=
approach does not scale to support compile time checking of </div><di=
v>> std::array bounds suggested by Alexander. </div><div>> =
</div><div>> std::array< int, 10 > arr; </div><div>>=
; arr[20] =3D 5; // compilation failure: index out of bounds </=
div><div><br></div><div>Yes it does. You just have to index the array with =
a `std::integral_constant`.</div><div><br></div><div>----------------------=
--------------------------------------------------------</div><div>#include=
<array></div><div>#include <cstddef></div><div>#include <ty=
pe_traits></div><div><br></div><div>constexpr int to_int(char c)</div><d=
iv>{ return static_cast<int>(c) - 48; }</div><div><br></div><div>temp=
late <std::size_t N></div><div>constexpr unsigned long parse(const ch=
ar (&arr)[N]) {</div><div> unsigned long number =3D 0, bas=
e =3D 1;</div><div> for (std::size_t i =3D 0; i < N; ++i) {=
</div><div> number +=3D to_int(arr[N - 1 - i]) *=
base;</div><div> base *=3D 10;</div><div> =
}</div><div> return number;</div><div>}</div><div><br>=
</div><div>template <char ...c></div><div>constexpr std::integral_con=
stant<unsigned long, parse<sizeof...(c)>({c...})></div><div>ope=
rator"" _c() { return {}; }</div><div><br></div><div>template <typename =
T, std::size_t N, typename Index></div><div>constexpr T at(std::array<=
;T, N> array, Index) {</div><div> static_assert(Index::valu=
e < N, "Array index out of bounds!");</div><div> return arr=
ay[Index::value];</div><div>}</div><div><br></div><div>int main() {</div><d=
iv> std::array<int, 3> a{{1, 2, 3}};</div><div> &n=
bsp; at(a, 2_c); // ok</div><div> at(a, 3_c); // error: static=
_assert failed "Array index out of bounds!"</div><div>}</div><div>---------=
---------------------------------------------------------------------</div>=
<div><br></div><div>This `_c` suffix and similar ideas are provided in the =
Hana library [1].</div><div><br></div><div><br></div><div>> > Also, t=
his approach makes it possible to have different implementations </div=
><div>> > that would otherwise fail to compile for different values o=
f `order` by </div><div>> > overloading the `store` functioon. I=
t is unclear to me how this might </div><div>> > be achieved wit=
h `constexpr` parameters, but I admit I haven't read the </div><div>&g=
t; > papers referrenced in previous posts. </div><div>> </d=
iv><div>> I'm not sure what you mean here, could you clarify? </div=
><div><br></div><div>What I mean is that with constexpr parameters, all the=
branches in the switch</div><div>are required to compile. For example, in =
the following, if `A()` does not </div><div>compile when the memory or=
der is `std::memory_order_consume`, then you will</div><div>get a hard erro=
r:</div><div><br></div><div> template <typename T> =
</div><div> void store(T val, constexpr memory_order order) {&=
nbsp;</div><div> switch (order) { </div><di=
v> case std::memory_order_relaxed:=
</div><div> A();</di=
v><div> break;</div>=
<div> </div><div>  =
; case std::memory_order_consume:</div><div> &nb=
sp; B();</div><div> =
break;</div><div> }</div><d=
iv> }</div><div><br></div><div>However, with what I sketched, =
you could instead have</div><div><br></div><div> template <=
typename T></div><div> void store(T val, memory_order_c<=
std::memory_order_relaxed>) {</div><div> A();=
</div><div> }</div><div><br></div><div> template =
<typename T></div><div> void store(T val, memory_order_c=
<std::memory_order_consume>) {</div><div> =
B();</div><div> }</div><div><br></div><div><br></div><div>This=
way, `A()` does not have to be a valid expression when </div><div>`st=
d::memory_order_consume` is sent to `store`, and similarly</div><div>for `B=
()` and `std::memory_order_relaxed`. It is unclear how </div><div>this=
would be of any use in this precise use case, but it is</div><div>very imp=
ortant in other settings.</div><div><br></div><div>Regards,</div><div>Louis=
</div><div><br></div><div>[1]: http://github.com/ldionne/hana</div><div><br=
></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_68_28166505.1428929361548--
------=_Part_67_644489539.1428929361548--
.
Author: Andrey Semashev <andrey.semashev@gmail.com>
Date: Mon, 13 Apr 2015 18:07:39 +0300
Raw View
On Monday 13 April 2015 05:49:21 Louis Dionne wrote:
> On Monday, 13 April 2015 03:53:59 UTC-4, Andrey Semashev wrote:
> > On Sunday 12 April 2015 15:41:35 Louis Dionne wrote:
> > > [...]
> > >
> > > Basically, you would use `memory_order_relaxed_c` to convey the fact
>
> that
>
> > > the information is known at compile-time, and
>
> `std::memory_order_relaxed`
>
> > > otherwise. Using `integral_constant` objects instead of raw non-type
> > > template parameters has the advantage of keeping a unified function
>
> call
>
> > > syntax.
> >
> > Yes, that is possible, although it would require a change in user's code.
>
> The
>
> > second store in your example would still be interpreted as having a
>
> "runtime"
>
> > argument, which is what I was trying to fix.
>
> That is true. What I'm suggesting is to explicitly mark the arguments as
> constexpr, while what you are asking for is for the compiler to mark them
> as such automatically.
But they are constexpr already, the compiler simply discards this information
on function call. You just encode this constant into the argument type,
sidestepping the language limitation.
> > Also, this approach does not scale to support compile time checking of
> > std::array bounds suggested by Alexander.
> >
> > std::array< int, 10 > arr;
> > arr[20] = 5; // compilation failure: index out of bounds
>
> Yes it does. You just have to index the array with a
> `std::integral_constant`.
[snip]
Oh, I see. I guess I'm not used to literal operators yet. :) I can't say I
like the suffix though, it seem to add unnecessary noise.
> > I'm not sure what you mean here, could you clarify?
>
> What I mean is that with constexpr parameters, all the branches in the
> switch
> are required to compile. For example, in the following, if `A()` does not
> compile when the memory order is `std::memory_order_consume`, then you will
> get a hard error:
>
> template <typename T>
> void store(T val, constexpr memory_order order) {
> switch (order) {
> case std::memory_order_relaxed:
> A();
> break;
>
> case std::memory_order_consume:
> B();
> break;
> }
> }
>
> However, with what I sketched, you could instead have
>
> template <typename T>
> void store(T val, memory_order_c<std::memory_order_relaxed>) {
> A();
> }
>
> template <typename T>
> void store(T val, memory_order_c<std::memory_order_consume>) {
> B();
> }
>
>
> This way, `A()` does not have to be a valid expression when
> `std::memory_order_consume` is sent to `store`, and similarly
> for `B()` and `std::memory_order_relaxed`. It is unclear how
> this would be of any use in this precise use case, but it is
> very important in other settings.
I see. Well, if constexpr parameters were possible then tag-based dispatch
would be possible as well:
template <typename T>
void store(T val, constexpr memory_order order) {
store_impl(val, integral_constant< memory_order, order >());
}
But I admit it would require this additional function to convert the constant
into type.
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: 3dw4rd@verizon.net
Date: Thu, 23 Apr 2015 12:58:39 -0700 (PDT)
Raw View
------=_Part_293_658535944.1429819119758
Content-Type: multipart/alternative;
boundary="----=_Part_294_2030377817.1429819119758"
------=_Part_294_2030377817.1429819119758
Content-Type: text/plain; charset=UTF-8
This is what I was wondering. Store could have been a mamber template
function. I really think that's what they are asking for. It's probably
just too late for that.
On the other hand, constexpr function arguments could be used in a template
dispatch function without making the calling function a function template:
template<typename T, memory_order O>
void
atomic<T>::__store(T val, constexpr memory_order order);
// Define partial specializations for each memory_order...
template<typename T>
void
atomic<T>::store(T val, constexpr memory_order order)
{
__store<T, order>(val);
}
I think this would be backwards compatible...
Maybe not.. You'd need some ABI to tell you about constexpr args.
These would be function templates by another name.
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_294_2030377817.1429819119758
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">This is what I was wondering. Store could have been =
a mamber template function. I really think that's what they are askin=
g for. It's probably just too late for that.<br><br>On the other hand=
, constexpr function arguments could be used in a template dispatch functio=
n without making the calling function a function template:<br><br><div clas=
s=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); border-col=
or: rgb(187, 187, 187); border-style: solid; border-width: 1px; word-wrap: =
break-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><br>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"><code class=3D"pr=
ettyprint"><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">template<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify"><</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"></span><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">typename</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> T, </span></code></span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><code class=3D"prett=
yprint"><span style=3D"color: #000;" class=3D"styled-by-prettify"><code cla=
ss=3D"prettyprint"><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><code class=3D"prettyprint"><span style=3D"color: #000;" class=3D"styled-=
by-prettify">memory_order O</span></code></span></code></span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">></span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br> </span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">void</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"><br> atomic</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify"><</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify">T</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">>::__</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">store</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">T val</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">,</span><span style=3D"color: #000;" 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"> memory_order order</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"></span></code></span>;<br><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><code class=3D"prettyprint"><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br></span> // Define partial spec=
ializations for each </code></span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><code class=3D"prettyprint"><code class=3D"prettyprint"><=
span style=3D"color: #000;" class=3D"styled-by-prettify"><code class=3D"pre=
ttyprint"><span style=3D"color: #000;" class=3D"styled-by-prettify">memory_=
order</span></code></span></code>...<br><br></code> </span><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">template</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"></span><span style=3D"color: #008;=
" class=3D"styled-by-prettify">typename</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> T</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">></span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br> </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">void<br> </span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify">atomic</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify">T</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">>::</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify">store</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">T val</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: #008;" class=3D"styled-by-prettify">constexpr</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> memory_order orde=
r</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"><br> =
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br> &=
nbsp; </span><span style=3D"color: #008;" class=3D"styled-by-prettify">__st=
ore<T, order></span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">(val</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify">;<br><=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> &nbs=
p; </span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></div=
></code></div><br>I think this would be backwards compatible...<br>Maybe no=
t.. You'd need some ABI to tell you about constexpr args.<br>These wo=
uld be function templates by another name.<br><br><iframe style=3D"padding:=
0px; position: absolute; top: 0px; left: 0px; width: 841px; height: 188px;=
visibility: hidden;" frameborder=3D"0"></iframe></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_294_2030377817.1429819119758--
------=_Part_293_658535944.1429819119758--
.
Author: Andrey Semashev <andrey.semashev@gmail.com>
Date: Thu, 23 Apr 2015 23:34:59 +0300
Raw View
On Sunday 12 April 2015 13:33:09 you wrote:
> Hi,
>
> I wonder if constexpr function arguments would be a useful addition to the
> standard.
[snip]
> template< typename T >
> void atomic<T>::store(T val, constexpr memory_order order)
> {
> switch (order) // order is always constexpr
> {
> // implementations with different memory ordering guarantees
> }
> }
I've given this idea more thought and there is one problem with it that I see
no easy way around. It's the address operator:
auto p = &atomic<T>::store;
First question, what would be the type of p here? It can't be
void(atomic<T>::*)(T, memory_order) because that would mean no constexpr
argument. And constexpr can't be in the signature either because, well, when
you call the function through this pointer you'll have to pass a runtime value
anyway.
The second question, what value does p have? My original proposal suggested
there would be separate function bodies for different constexpr arguments.
These arguments are not present in the address taking operation which makes it
ambiguous.
We could say that address operator forces the compiler to generate a body with
runtime arguments. This makes the constexpr qualifier opportunistic, which
basically means constexpr arguments cannot be reliably used in constant
expressions and severely undermines its usefulness.
So it seems, the idea is a no go. We probably need another way to fix
std::atomic interface.
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Thu, 23 Apr 2015 13:49:29 -0700
Raw View
--047d7b33cb1887b05b05146a6aa5
Content-Type: text/plain; charset=UTF-8
On Sun, Apr 12, 2015 at 3:33 AM, Andrey Semashev <andrey.semashev@gmail.com>
wrote:
> Hi,
>
> I wonder if constexpr function arguments would be a useful addition to the
> standard.
This was brought up during standardization of C++11 and while a lot of
people would like it, myself included, I think the main problem was that it
would complicate the (already complicated) overload resolution rules. In
their current state, constexpr functions don't behave particularly special
regarding overload resolution, but if you could have individual constexpr
parameter types, especially ones that can be overloads of other functions
(and the ability to use those arguments as compile-time constant values in
the body of the function and other parts of the function signature, etc.),
then that would make the language more complicated in ways that many people
would not be in favor of. Anything that changes overload resolution is
pretty scary.
If someone really wants to fight that battle now, that'd be awesome. I'd
love it. My personal favorite examples are with pow-like functions. I'd
really like to be able to simply do:
assert(pow(2, 2), 4);
assert(pow(2_feet, 2) == 4_square_feet);
You can always simulate this stuff with integral_constant, or with explicit
template parameters, which is what such libraries currently do, but it
always feels a bit hacky. That and the idea that some operations can be
more optimal when one or more arguments are known at compile-time are
pretty compelling to me. If some internal, generic function can be more
optimal when used with a compile-time constant, and higher-level generic
functions that invoke it can be called either with runtime or compile-time
values, the constexpr-like optimization could be made to appear as an
implementation-detail to the user, with the calling code looking no
different and the constexpr-ness of one or more arguments propagating along
when forwarded. This last point is theoretical right now, but it wouldn't
surprise me if compelling examples could arise when such experimental
facilities are available to library developers. The propagation of
constexpr-ness of individual arguments and the ability to dispatch
overloads based on that information seems very much in line with the
principles of generic programming in C++ libraries.
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--047d7b33cb1887b05b05146a6aa5
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On S=
un, Apr 12, 2015 at 3:33 AM, Andrey Semashev <span dir=3D"ltr"><<a href=
=3D"mailto:andrey.semashev@gmail.com" target=3D"_blank">andrey.semashev@gma=
il.com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"=
margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,20=
4,204);border-left-style:solid;padding-left:1ex">Hi,<br>
<br>
I wonder if constexpr function arguments would be a useful addition to the<=
br>
standard.</blockquote><div><br></div><div>This was brought up during standa=
rdization of C++11 and while a lot of people would like it, myself included=
, I think the main problem was that it would complicate the (already compli=
cated) overload resolution rules. In their current state, constexpr functio=
ns don't behave particularly special regarding overload resolution, but=
if you could have individual constexpr parameter types, especially ones th=
at can be overloads of other functions (and the ability to use those argume=
nts as compile-time constant values in the body of the function and other p=
arts of the function signature, etc.), then that would make the language mo=
re complicated in ways that many people would not be in favor of. Anything =
that changes overload resolution is pretty scary.</div><div><br></div><div>=
If someone really wants to fight that battle now, that'd be awesome. I&=
#39;d love it. My personal favorite examples are with pow-like functions. I=
'd really like to be able to simply do:</div><div><br></div><div>assert=
(pow(2, 2), 4);</div><div>assert(pow(2_feet, 2) =3D=3D 4_square_feet);=C2=
=A0</div><div><br></div><div>You can always simulate this stuff with integr=
al_constant, or with explicit template parameters, which is what such libra=
ries currently do, but it always feels a bit hacky. That and the idea that =
some operations can be more optimal when one or more arguments are known at=
compile-time are pretty compelling to me. If some internal, generic functi=
on can be more optimal when used with a compile-time constant, and higher-l=
evel generic functions that invoke it can be called either with runtime or =
compile-time values, the constexpr-like optimization could be made to appea=
r as an implementation-detail to the user, with the calling code looking no=
different and the constexpr-ness of one or more arguments propagating alon=
g when forwarded. This last point is theoretical right now, but it wouldn&#=
39;t surprise me if compelling examples could arise when such experimental =
facilities are available to library developers. The propagation of constexp=
r-ness of individual arguments and the ability to dispatch overloads based =
on that information seems very much in line with the principles of generic =
programming in C++ libraries.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7b33cb1887b05b05146a6aa5--
.
Author: Andrey Semashev <andrey.semashev@gmail.com>
Date: Fri, 24 Apr 2015 00:09:59 +0300
Raw View
On Thursday 23 April 2015 13:49:29 'Matt Calabrese' via ISO C++ Standard -
Future Proposals wrote:
> On Sun, Apr 12, 2015 at 3:33 AM, Andrey Semashev <andrey.semashev@gmail.com>
> wrote:
> > Hi,
> >
> > I wonder if constexpr function arguments would be a useful addition to the
> > standard.
>
> This was brought up during standardization of C++11 and while a lot of
> people would like it, myself included, I think the main problem was that it
> would complicate the (already complicated) overload resolution rules. In
> their current state, constexpr functions don't behave particularly special
> regarding overload resolution, but if you could have individual constexpr
> parameter types, especially ones that can be overloads of other functions
> (and the ability to use those arguments as compile-time constant values in
> the body of the function and other parts of the function signature, etc.),
> then that would make the language more complicated in ways that many people
> would not be in favor of. Anything that changes overload resolution is
> pretty scary.
>
> If someone really wants to fight that battle now, that'd be awesome. I'd
> love it. My personal favorite examples are with pow-like functions. I'd
> really like to be able to simply do:
>
> assert(pow(2, 2), 4);
> assert(pow(2_feet, 2) == 4_square_feet);
>
> You can always simulate this stuff with integral_constant, or with explicit
> template parameters, which is what such libraries currently do, but it
> always feels a bit hacky. That and the idea that some operations can be
> more optimal when one or more arguments are known at compile-time are
> pretty compelling to me. If some internal, generic function can be more
> optimal when used with a compile-time constant, and higher-level generic
> functions that invoke it can be called either with runtime or compile-time
> values, the constexpr-like optimization could be made to appear as an
> implementation-detail to the user, with the calling code looking no
> different and the constexpr-ness of one or more arguments propagating along
> when forwarded. This last point is theoretical right now, but it wouldn't
> surprise me if compelling examples could arise when such experimental
> facilities are available to library developers. The propagation of
> constexpr-ness of individual arguments and the ability to dispatch
> overloads based on that information seems very much in line with the
> principles of generic programming in C++ libraries.
It would be great if constexpr-ness just transparently propagated into the
function body, but then the function would likely need an intrinsic to detect
if a certain argument (or more generically speaking, an expression) is a
constant expression. Say, an is_constexpr() operator, which returns a
constexpr bool. Do you think such addition would be more feasible?
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Thu, 23 Apr 2015 14:30:26 -0700
Raw View
--089e0118289cf626f105146afc91
Content-Type: text/plain; charset=UTF-8
On Thu, Apr 23, 2015 at 2:09 PM, Andrey Semashev <andrey.semashev@gmail.com>
wrote:
> It would be great if constexpr-ness just transparently propagated into the
> function body, but then the function would likely need an intrinsic to
> detect
> if a certain argument (or more generically speaking, an expression) is a
> constant expression. Say, an is_constexpr() operator, which returns a
> constexpr bool. Do you think such addition would be more feasible?
>
IMO, an operator to check constexpr-ness could/should already exist now,
separate from other concerns. It would work similar to the ability to use
noexcept to get a compile-time constant that says if a given expression
composed of all noexcept operations. This is actually surprisingly tricky
to do without an intrinsic operator in current C++ (though at least
partially possible) and it necessarily requires use in an evaluated context
as opposed to an unevaluated one.
As for whether constexpr-ness could truly transparently propagate, I think
it wouldn't be quite so simple to make it actually transparent as it likely
would involve making changes to the type system (unless people see other
routes forward). The way I imagine it would be done is by having constexpr
become something closer to a cv-qualifier, making it able to be forwarded
along in the same way that cv-qualifiers are forwarded implicitly via
template parameter deduction and std::forward. This would be a complicated
change though, and it has the implication that a template instantiated with
a constexpr object would be a different instantiation than one instantiated
with a non-constexpr object, which is... unfortunate, though I don't know
if alternatives would really be feasible without sacrificing overall
functionality.
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e0118289cf626f105146afc91
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On T=
hu, Apr 23, 2015 at 2:09 PM, Andrey Semashev <span dir=3D"ltr"><<a href=
=3D"mailto:andrey.semashev@gmail.com" target=3D"_blank">andrey.semashev@gma=
il.com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"=
margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div cl=
ass=3D"h5"><span style=3D"color:rgb(34,34,34)">It would be great if constex=
pr-ness just transparently propagated into the</span><br></div></div>
function body, but then the function would likely need an intrinsic to dete=
ct<br>
if a certain argument (or more generically speaking, an expression) is a<br=
>
constant expression. Say, an is_constexpr() operator, which returns a<br>
constexpr bool. Do you think such addition would be more feasible?<br></blo=
ckquote><div><br></div><div>IMO, an operator to check constexpr-ness could/=
should already exist now, separate from other concerns. It would work simil=
ar to the ability to use noexcept to get a compile-time constant that says =
if a given expression composed of all noexcept operations. This is actually=
surprisingly tricky to do without an intrinsic operator in current C++ (th=
ough at least partially possible) and it necessarily requires use in an eva=
luated context as opposed to an unevaluated one.</div><div><br></div><div>A=
s for whether constexpr-ness could truly transparently propagate, I think i=
t wouldn't be quite so simple to make it actually transparent as it lik=
ely would involve making changes to the type system (unless people see othe=
r routes forward). The way I imagine it would be done is by having constexp=
r become something closer to a cv-qualifier, making it able to be forwarded=
along in the same way that cv-qualifiers are forwarded implicitly via temp=
late parameter deduction and std::forward. This would be a complicated chan=
ge though, and it has the implication that a template instantiated with a c=
onstexpr object would be a different instantiation than one instantiated wi=
th a non-constexpr object, which is... unfortunate, though I don't know=
if alternatives would really be feasible without sacrificing overall funct=
ionality.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e0118289cf626f105146afc91--
.
Author: Andrey Semashev <andrey.semashev@gmail.com>
Date: Fri, 24 Apr 2015 01:15:27 +0300
Raw View
On Thursday 23 April 2015 14:30:26 'Matt Calabrese' via ISO C++ Standard -
Future Proposals wrote:
> On Thu, Apr 23, 2015 at 2:09 PM, Andrey Semashev <andrey.semashev@gmail.com>
> wrote:
> > It would be great if constexpr-ness just transparently propagated into the
> > function body, but then the function would likely need an intrinsic to
> > detect
> > if a certain argument (or more generically speaking, an expression) is a
> > constant expression. Say, an is_constexpr() operator, which returns a
> > constexpr bool. Do you think such addition would be more feasible?
[snip]
> As for whether constexpr-ness could truly transparently propagate, I think
> it wouldn't be quite so simple to make it actually transparent as it likely
> would involve making changes to the type system (unless people see other
> routes forward).
Isn't it possible to just describe the rules under which constexpr-ness should
propagate without changing the type system? Something like "if the function
argument is initialized with a constant expression, and the function
definition is visible at the call site then that argument is a constexpr
within that function body in the context of that particular call." Function-
local static variables would still have to be shared between all constexpr or
not calls to such function but I think it's not a problem. The address
operator would return a pointer to the function that takes runtime arguments.
All in all it would appear as if for some calls the function has shadow
specializations which are not detectable other than by calling them.
It could result in code bloat though. So it's probably better to mark such
arguments with constexpr so that such special rules are applied only where
needed. It wouldn't affect overload resolution because the function is the
same (as constexpr would not participate in the function type).
template< typename T >
void atomic<T>::store(T val, constexpr memory_order order)
{
// ...
}
atomic<T> a;
memory_order o = memory_order_relaxed;
a.store(10, o); // order is not constexpr within store(); the fully runtime
// version of store() is called
a.store(10, memory_order_relaxed); // order is constexpr within store();
// a shadow version of store() is called
auto p = &atomic<T>::store; // decltype(p) is
// void (atomic<T>::*)(T, memory_order);
// p points to the fully runtime version
// of store()
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Thu, 23 Apr 2015 16:13:27 -0700
Raw View
--047d7bd7648e665c7805146c6d11
Content-Type: text/plain; charset=UTF-8
On Thu, Apr 23, 2015 at 3:15 PM, Andrey Semashev <andrey.semashev@gmail.com>
wrote:
> Isn't it possible to just describe the rules under which constexpr-ness
> should
> propagate without changing the type system? Something like "if the function
> argument is initialized with a constant expression, and the function
> definition is visible at the call site then that argument is a constexpr
> within that function body in the context of that particular call."
Assuming for a moment that this were feasible, inside of the function (and
as a part of the rest of the signature), I think you'd need functionality
equivalent to a "static if" kind of facility, otherwise you wouldn't
realistically be able to use your object as a compile-time constant in the
function body or in other parts of the function signature. In other words,
imagine:
template <class T>
unsigned pow(T&& base, unsigned exponent)
{
if( constexpr( exponent ) )
{
// This branch would actually require a static-if like facility
// since we are using exponent as a compile-time constant
return optimized_pow<exponent>(std::forward<T>(base));
}
else
{
return /*runtime-power-operation*/;
}
}
The "if the definition is visible" also seems really scary. The definition
should probably always be visible if you invoke it at all, otherwise I can
imagine it would be very easy to get ODR violations.
Also, I realize now that my saying that constexpr could be more-like a
cv-qualifier to a parameter type isn't even enough, since you effectively
would need a different function for each /value/ and not just for each
type. Again, consider the pow-with-units example:
(pow(2_feet, 2) == 4_square_feet);
In the above code, the return type of pow is dependent on the value of the
exponent. An exponent of 1 yields a quantity in feet, an exponent of 2
yields a quantity in feet squared, etc. Really, for this to be useful, IMO,
pow(2_feet, 2) should be just as powerful as pow(2_feet,
std::integral_constant<int, 2>), which would require the functions to
actually be different, since both their definition and their signature
would differ and there could also be arbitrary compile-time branching based
on the value.
I think the way things would probably have to work in C++ is that the
constexpr-ness and value both somehow get encoded into the type when the
constexpr object is passed as an argument I.E. equivalent to passing it as
a std::integral_constant, but it would work for any literal type. This has
problems regarding equivalence of literal values, making look-up of
instantiations difficult, is one reason why user-defined literal types
cannot be template arguments in existing C++ already, which was initially
considered for C++11.
Ultimately, I think in order for everything to be done "right," some
considerable changes would need to be made to the language.
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--047d7bd7648e665c7805146c6d11
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On T=
hu, Apr 23, 2015 at 3:15 PM, Andrey Semashev <span dir=3D"ltr"><<a href=
=3D"mailto:andrey.semashev@gmail.com" target=3D"_blank">andrey.semashev@gma=
il.com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"=
margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,20=
4,204);border-left-style:solid;padding-left:1ex">Isn't it possible to j=
ust describe the rules under which constexpr-ness should<br>
propagate without changing the type system? Something like "if the fun=
ction<br>
argument is initialized with a constant expression, and the function<br>
definition is visible at the call site then that argument is a constexpr<br=
>
within that function body in the context of that particular call."</bl=
ockquote><div><br></div><div>Assuming for a moment that this were feasible,=
inside of the function (and as a part of the rest of the signature), I thi=
nk you'd need functionality equivalent to a "static if" kind =
of facility, otherwise you wouldn't realistically be able to use your o=
bject as a compile-time constant in the function body or in other parts of =
the function signature. In other words, imagine:</div><div><br></div><div>t=
emplate <class T></div><div>unsigned pow(T&& base, unsigned e=
xponent)</div><div>{</div><div>=C2=A0 if( constexpr( exponent ) )</div><div=
>=C2=A0 {</div><div>=C2=A0 =C2=A0 // This branch would actually require a s=
tatic-if like facility</div><div>=C2=A0 =C2=A0 // since we are using expone=
nt as a compile-time constant</div><div>=C2=A0 =C2=A0 return optimized_pow&=
lt;exponent>(std::forward<T>(base));</div><div>=C2=A0 }</div><div>=
=C2=A0 else</div><div>=C2=A0 {</div><div>=C2=A0 =C2=A0 return /*runtime-pow=
er-operation*/;</div><div>=C2=A0 }</div><div>}</div><div><br></div><div>The=
"if the definition is visible" also seems really scary. The defi=
nition should probably always be visible if you invoke it at all, otherwise=
I can imagine it would be very easy to get ODR violations.</div><div><br><=
/div><div>Also, I realize now that my saying that constexpr could be more-l=
ike a cv-qualifier to a parameter type isn't even enough, since you eff=
ectively would need a different function for each /value/ and not just for =
each type. Again, consider the pow-with-units example:</div><div><br></div>=
<div>(pow(2_feet, 2) =3D=3D 4_square_feet);</div><div><br></div><div>In the=
above code, the return type of pow is dependent on the value of the expone=
nt. An exponent of 1 yields a quantity in feet, an exponent of 2 yields a q=
uantity in feet squared, etc. Really, for this to be useful, IMO, pow(2_fee=
t, 2) should be just as powerful as pow(2_feet, std::integral_constant<i=
nt, 2>), which would require the functions to actually be different, sin=
ce both their definition and their signature would differ and there could a=
lso be arbitrary compile-time branching based on the value.</div><div><br><=
/div><div>I think the way things would probably have to work in C++ is that=
the constexpr-ness and value both somehow get encoded into the type when t=
he constexpr object is passed as an argument I.E. equivalent to passing it =
as a std::integral_constant, but it would work for any literal type. This h=
as problems regarding equivalence of literal values, making look-up of inst=
antiations difficult, is one reason why user-defined literal types cannot b=
e template arguments in existing C++ already, which was initially considere=
d for C++11.</div><div><br></div><div>Ultimately, I think in order for ever=
ything to be done "right," some considerable changes would need t=
o be made to the language.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7bd7648e665c7805146c6d11--
.
Author: Andrey Semashev <andrey.semashev@gmail.com>
Date: Fri, 24 Apr 2015 12:07:16 +0300
Raw View
On Thursday 23 April 2015 16:13:27 'Matt Calabrese' via ISO C++ Standard -
Future Proposals wrote:
> On Thu, Apr 23, 2015 at 3:15 PM, Andrey Semashev <andrey.semashev@gmail.com>
> wrote:
> > Isn't it possible to just describe the rules under which constexpr-ness
> > should
> > propagate without changing the type system? Something like "if the
> > function
> > argument is initialized with a constant expression, and the function
> > definition is visible at the call site then that argument is a constexpr
> > within that function body in the context of that particular call."
>
> Assuming for a moment that this were feasible, inside of the function (and
> as a part of the rest of the signature), I think you'd need functionality
> equivalent to a "static if" kind of facility, otherwise you wouldn't
> realistically be able to use your object as a compile-time constant in the
> function body or in other parts of the function signature.
If we have is_constexpr operator suggested earlier, tag-based dispatch is also
possible:
template <class T>
unsigned pow(T&& base, constexpr unsigned exponent)
{
return pow_impl(std::forward<T>(base), exponent,
std::integral_constant< bool, is_constexpr(exponent) >());
}
> The "if the definition is visible" also seems really scary. The definition
> should probably always be visible if you invoke it at all, otherwise I can
> imagine it would be very easy to get ODR violations.
Not sure I understand. What I meant is that the function body has to be
visible in the current translation unit, so that its shadow version can be
generated. It's similar to function templates - you have to make the template
definition visible so that it can be instantiated at the call site, or
explicitly instantiate it with the same template parameters elsewhere.
> Also, I realize now that my saying that constexpr could be more-like a
> cv-qualifier to a parameter type isn't even enough, since you effectively
> would need a different function for each /value/ and not just for each
> type. Again, consider the pow-with-units example:
>
> (pow(2_feet, 2) == 4_square_feet);
>
> In the above code, the return type of pow is dependent on the value of the
> exponent. An exponent of 1 yields a quantity in feet, an exponent of 2
> yields a quantity in feet squared, etc. Really, for this to be useful, IMO,
> pow(2_feet, 2) should be just as powerful as pow(2_feet,
> std::integral_constant<int, 2>), which would require the functions to
> actually be different, since both their definition and their signature
> would differ and there could also be arbitrary compile-time branching based
> on the value.
Well, you could potentially do something like this:
template <class T>
powered<T, exponent> pow_impl(
T&& base, constexpr unsigned exponent, std::true_type)
{
return powered<T, exponent>(std::forward<T>(base), exponent);
}
template <class T>
T pow_impl(T&& base, unsigned exponent, std::false_type)
{
return std::pow(base, exponent);
}
template <class T>
auto pow(T&& base, constexpr unsigned exponent) ->
decltype(pow_impl(std::forward<T>(base), exponent,
std::integral_constant< bool, is_constexpr(exponent) >()))
{
return pow_impl(std::forward<T>(base), exponent,
std::integral_constant< bool, is_constexpr(exponent) >());
}
Hmm, now I'm starting to understand what you meant by ODR violations. So the
proposal doesn't work if we allow the constexpr argument affect the function
type.
> I think the way things would probably have to work in C++ is that the
> constexpr-ness and value both somehow get encoded into the type when the
> constexpr object is passed as an argument I.E. equivalent to passing it as
> a std::integral_constant, but it would work for any literal type. This has
> problems regarding equivalence of literal values, making look-up of
> instantiations difficult, is one reason why user-defined literal types
> cannot be template arguments in existing C++ already, which was initially
> considered for C++11.
>
> Ultimately, I think in order for everything to be done "right," some
> considerable changes would need to be made to the language.
I see. Thank you for your comments.
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: szollosi.lorand@gmail.com
Date: Fri, 16 Dec 2016 15:41:29 -0800 (PST)
Raw View
------=_Part_769_424986654.1481931689534
Content-Type: multipart/alternative;
boundary="----=_Part_770_1936373955.1481931689535"
------=_Part_770_1936373955.1481931689535
Content-Type: text/plain; charset=UTF-8
Hi,
Motivation:
Member functions pointers. Every compile-time parameter can be represented
as a template argument, but a constexpr parameter could resolve multiple
template arguments. Consider e.g.:
// register_callback() is external - either a fn or a ctor which we can't
modify
using void_callback = void (*)();
extern void register_callback(void *, void_callback);
// old syntax (note that MyType is duplicated)
// usage: register_callback(this, member_callback<MyType, &MyType::MyFN>);
template<typename T, void (T::*func)()>
void_callback member_callback() {
return +[](void *that){ static_cast<T*>(that)->func(); };
}
// new syntax
// usage: register_callback(this, member_callback_simple(&MyType::MyFN));
template<typename T>
auto member_callback_simple(constexpr void (T::*func)) {
return member_callback<T, func>();
}
Further use cases are metafunctions that depend on a function's signature
and simpler template metaprogramming constructs.
- Do you think it's valid and fits in C++?
- Is there anyone working on similar proposal(s)?
Thanks in advance,
-lorro
--
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/87553b7e-4e20-4758-baf4-5fcbd9298176%40isocpp.org.
------=_Part_770_1936373955.1481931689535
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Hi,<br><br>Motivation:<br>Member functions pointers. Every=
compile-time parameter can be represented as a template argument, but a co=
nstexpr parameter could resolve multiple template arguments. Consider e.g.:=
<br><br><div style=3D"background-color: rgb(250, 250, 250); border-color: r=
gb(187, 187, 187); border-style: solid; border-width: 1px; overflow-wrap: b=
reak-word;" class=3D"prettyprint"><code class=3D"prettyprint"><div class=3D=
"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">=
// register_callback() is external - either a fn or a ctor which we can'=
;t modify<br>using</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> void_callback </span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">voi=
d</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">(*)();</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">extern</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #0=
08;" class=3D"styled-by-prettify">void</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> register_callback</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">void</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">*,</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> void_callback</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">);</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br><br>// old syntax (note that MyType is duplicated)<br></span><span styl=
e=3D"color: #800;" class=3D"styled-by-prettify">// usage: register_callback=
(this, member_callback<MyType, &MyType::MyFN>);</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">template</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">typename</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> T</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">void</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify">T</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">::*</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify">func</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">)()></span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br>void_callback member_callback</span><sp=
an 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-by-prettify">{</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color:=
#008;" class=3D"styled-by-prettify">return</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">+[](</span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">void</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">*</span><span style=3D"color: #000;" class=3D"styled-by-prettify">that</=
span><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: #008;" class=3D"styled-by-prettify">static_cast</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">T</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">*>(</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify">that</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">)-></span><span style=3D"color: #000;" class=3D"=
styled-by-prettify">func</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">();</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">};=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br></span><br>// new syn=
tax<br><code class=3D"prettyprint"><span style=3D"color: #800;" class=3D"st=
yled-by-prettify">// usage: register_callback(this, member_callback_simple(=
&MyType::MyFN));</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br></span></code><span style=3D"color: #008;" class=3D"styled-by=
-prettify">template</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify"><</span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">typename</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> T</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><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">auto</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> member_callback_simple</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">constexpr</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D=
"color: #008;" class=3D"styled-by-prettify">void</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify">T</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">::*</span><span style=3D"background-color: rgb(255, 255, 0);"><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify">func</span></span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify">) {<br>=C2=A0=C2=A0=C2=A0 r=
eturn member_callback<T, <span style=3D"background-color: rgb(255, 255, =
0);">func</span>>();<br>}<br></span></div></code></div><br>Further use c=
ases are metafunctions that depend on a function's signature and simple=
r template metaprogramming constructs.<br><br>- Do you think it's valid=
and fits in C++?<br>- Is there anyone working on similar proposal(s)?<br><=
br>Thanks in advance,<br>-lorro<br></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;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/87553b7e-4e20-4758-baf4-5fcbd9298176%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/87553b7e-4e20-4758-baf4-5fcbd9298176=
%40isocpp.org</a>.<br />
------=_Part_770_1936373955.1481931689535--
------=_Part_769_424986654.1481931689534--
.
Author: Richard Smith <richard@metafoo.co.uk>
Date: Fri, 16 Dec 2016 15:57:30 -0800
Raw View
--047d7b6251a077ae7f0543cf568c
Content-Type: text/plain; charset=UTF-8
On 16 December 2016 at 15:41, <szollosi.lorand@gmail.com> wrote:
> Hi,
>
> Motivation:
> Member functions pointers. Every compile-time parameter can be represented
> as a template argument, but a constexpr parameter could resolve multiple
> template arguments. Consider e.g.:
>
> // register_callback() is external - either a fn or a ctor which we can't
> modify
> using void_callback = void (*)();
> extern void register_callback(void *, void_callback);
>
> // old syntax (note that MyType is duplicated)
> // usage: register_callback(this, member_callback<MyType, &MyType::MyFN>);
> template<typename T, void (T::*func)()>
> void_callback member_callback() {
> return +[](void *that){ static_cast<T*>(that)->func(); };
> }
>
> // new syntax
> // usage: register_callback(this, member_callback_simple(&MyType::MyFN));
> template<typename T>
> auto member_callback_simple(constexpr void (T::*func)) {
> return member_callback<T, func>();
> }
>
> Further use cases are metafunctions that depend on a function's signature
> and simpler template metaprogramming constructs.
>
> - Do you think it's valid and fits in C++?
> - Is there anyone working on similar proposal(s)?
>
Try searching the archives of this list; this has been suggested several
times before.
--
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/CAOfiQq%3DFG50q4NhqY1L41HPSL-ZJ7U%2B%3DFZURJyYKobKsSW9NHA%40mail.gmail.com.
--047d7b6251a077ae7f0543cf568c
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On 1=
6 December 2016 at 15:41, <span dir=3D"ltr"><<a href=3D"mailto:szollosi=
..lorand@gmail.com" target=3D"_blank">szollosi.lorand@gmail.com</a>></spa=
n> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;b=
order-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">Hi,<br><br>Mot=
ivation:<br>Member functions pointers. Every compile-time parameter can be =
represented as a template argument, but a constexpr parameter could resolve=
multiple template arguments. Consider e.g.:<br><br><div style=3D"backgroun=
d-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;b=
order-width:1px" class=3D"m_-7280704993387610058prettyprint"><code class=3D=
"m_-7280704993387610058prettyprint"><div class=3D"m_-7280704993387610058sub=
prettyprint"><span style=3D"color:#008" class=3D"m_-7280704993387610058styl=
ed-by-prettify">// register_callback() is external - either a fn or a ctor =
which we can't modify<br>using</span><span style=3D"color:#000" class=
=3D"m_-7280704993387610058styled-by-prettify"> void_callback </span><span s=
tyle=3D"color:#660" class=3D"m_-7280704993387610058styled-by-prettify">=3D<=
/span><span style=3D"color:#000" class=3D"m_-7280704993387610058styled-by-p=
rettify"> </span><span style=3D"color:#008" class=3D"m_-7280704993387610058=
styled-by-prettify">void</span><span style=3D"color:#000" class=3D"m_-72807=
04993387610058styled-by-prettify"> </span><span style=3D"color:#660" class=
=3D"m_-7280704993387610058styled-by-prettify">(*)();</span><span style=3D"c=
olor:#000" class=3D"m_-7280704993387610058styled-by-prettify"><br></span><s=
pan style=3D"color:#008" class=3D"m_-7280704993387610058styled-by-prettify"=
>extern</span><span style=3D"color:#000" class=3D"m_-7280704993387610058sty=
led-by-prettify"> </span><span style=3D"color:#008" class=3D"m_-72807049933=
87610058styled-by-prettify">void</span><span style=3D"color:#000" class=3D"=
m_-7280704993387610058styled-by-prettify"> register_callback</span><span st=
yle=3D"color:#660" class=3D"m_-7280704993387610058styled-by-prettify">(</sp=
an><span style=3D"color:#008" class=3D"m_-7280704993387610058styled-by-pret=
tify">void</span><span style=3D"color:#000" class=3D"m_-7280704993387610058=
styled-by-prettify"> </span><span style=3D"color:#660" class=3D"m_-72807049=
93387610058styled-by-prettify">*,</span><span style=3D"color:#000" class=3D=
"m_-7280704993387610058styled-by-prettify"> void_callback</span><span style=
=3D"color:#660" class=3D"m_-7280704993387610058styled-by-prettify">);</span=
><span style=3D"color:#000" class=3D"m_-7280704993387610058styled-by-pretti=
fy"><br><br>// old syntax (note that MyType is duplicated)<br></span><span =
style=3D"color:#800" class=3D"m_-7280704993387610058styled-by-prettify">// =
usage: register_callback(this, member_callback<MyType, &MyType::MyFN=
>);</span><span style=3D"color:#000" class=3D"m_-7280704993387610058styl=
ed-by-prettify"><br></span><span style=3D"color:#008" class=3D"m_-728070499=
3387610058styled-by-prettify">template</span><span style=3D"color:#660" cla=
ss=3D"m_-7280704993387610058styled-by-prettify"><</span><span style=3D"c=
olor:#008" class=3D"m_-7280704993387610058styled-by-prettify">typename</spa=
n><span style=3D"color:#000" class=3D"m_-7280704993387610058styled-by-prett=
ify"> T</span><span style=3D"color:#660" class=3D"m_-7280704993387610058sty=
led-by-prettify">,</span><span style=3D"color:#000" class=3D"m_-72807049933=
87610058styled-by-prettify"> </span><span style=3D"color:#008" class=3D"m_-=
7280704993387610058styled-by-prettify">void</span><span style=3D"color:#000=
" class=3D"m_-7280704993387610058styled-by-prettify"> </span><span style=3D=
"color:#660" class=3D"m_-7280704993387610058styled-by-prettify">(</span><sp=
an style=3D"color:#000" class=3D"m_-7280704993387610058styled-by-prettify">=
T</span><span style=3D"color:#660" class=3D"m_-7280704993387610058styled-by=
-prettify">::*</span><span style=3D"color:#000" class=3D"m_-728070499338761=
0058styled-by-prettify">func</span><span style=3D"color:#660" class=3D"m_-7=
280704993387610058styled-by-prettify">)()></span><span style=3D"color:#0=
00" class=3D"m_-7280704993387610058styled-by-prettify"><br>void_callback me=
mber_callback</span><span style=3D"color:#660" class=3D"m_-7280704993387610=
058styled-by-prettify">()</span><span style=3D"color:#000" class=3D"m_-7280=
704993387610058styled-by-prettify"> </span><span style=3D"color:#660" class=
=3D"m_-7280704993387610058styled-by-prettify">{</span><span style=3D"color:=
#000" class=3D"m_-7280704993387610058styled-by-prettify"><br>=C2=A0 =C2=A0 =
</span><span style=3D"color:#008" class=3D"m_-7280704993387610058styled-by-=
prettify">return</span><span style=3D"color:#000" class=3D"m_-7280704993387=
610058styled-by-prettify"> </span><span style=3D"color:#660" class=3D"m_-72=
80704993387610058styled-by-prettify">+[](</span><span style=3D"color:#008" =
class=3D"m_-7280704993387610058styled-by-prettify">void</span><span style=
=3D"color:#000" class=3D"m_-7280704993387610058styled-by-prettify"> </span>=
<span style=3D"color:#660" class=3D"m_-7280704993387610058styled-by-prettif=
y">*</span><span style=3D"color:#000" class=3D"m_-7280704993387610058styled=
-by-prettify">that</span><span style=3D"color:#660" class=3D"m_-72807049933=
87610058styled-by-prettify">){</span><span style=3D"color:#000" class=3D"m_=
-7280704993387610058styled-by-prettify"> </span><span style=3D"color:#008" =
class=3D"m_-7280704993387610058styled-by-prettify">static_cast</span><span =
style=3D"color:#660" class=3D"m_-7280704993387610058styled-by-prettify"><=
;</span><span style=3D"color:#000" class=3D"m_-7280704993387610058styled-by=
-prettify">T</span><span style=3D"color:#660" class=3D"m_-72807049933876100=
58styled-by-prettify">*>(</span><span style=3D"color:#000" class=3D"m_-7=
280704993387610058styled-by-prettify">that</span><span style=3D"color:#660"=
class=3D"m_-7280704993387610058styled-by-prettify">)-></span><span styl=
e=3D"color:#000" class=3D"m_-7280704993387610058styled-by-prettify">func</s=
pan><span style=3D"color:#660" class=3D"m_-7280704993387610058styled-by-pre=
ttify">();</span><span style=3D"color:#000" class=3D"m_-7280704993387610058=
styled-by-prettify"> </span><span style=3D"color:#660" class=3D"m_-72807049=
93387610058styled-by-prettify">};</span><span style=3D"color:#000" class=3D=
"m_-7280704993387610058styled-by-prettify"><br></span><span style=3D"color:=
#660" class=3D"m_-7280704993387610058styled-by-prettify">}</span><span styl=
e=3D"color:#000" class=3D"m_-7280704993387610058styled-by-prettify"><br></s=
pan><br>// new syntax<br><code class=3D"m_-7280704993387610058prettyprint">=
<span style=3D"color:#800" class=3D"m_-7280704993387610058styled-by-prettif=
y">// usage: register_callback(this, member_callback_simple(&<wbr>MyTyp=
e::MyFN));</span><span style=3D"color:#000" class=3D"m_-7280704993387610058=
styled-by-prettify"><br></span></code><span style=3D"color:#008" class=3D"m=
_-7280704993387610058styled-by-prettify">template</span><span style=3D"colo=
r:#660" class=3D"m_-7280704993387610058styled-by-prettify"><</span><span=
style=3D"color:#008" class=3D"m_-7280704993387610058styled-by-prettify">ty=
pename</span><span style=3D"color:#000" class=3D"m_-7280704993387610058styl=
ed-by-prettify"> T</span><span style=3D"color:#660" class=3D"m_-72807049933=
87610058styled-by-prettify">></span><span style=3D"color:#000" class=3D"=
m_-7280704993387610058styled-by-prettify"><br></span><span style=3D"color:#=
008" class=3D"m_-7280704993387610058styled-by-prettify">auto</span><span st=
yle=3D"color:#000" class=3D"m_-7280704993387610058styled-by-prettify"> memb=
er_callback_simple</span><span style=3D"color:#660" class=3D"m_-72807049933=
87610058styled-by-prettify">(</span><span style=3D"color:#008" class=3D"m_-=
7280704993387610058styled-by-prettify">constex<wbr>pr</span><span style=3D"=
color:#000" class=3D"m_-7280704993387610058styled-by-prettify"> </span><spa=
n style=3D"color:#008" class=3D"m_-7280704993387610058styled-by-prettify">v=
oid</span><span style=3D"color:#000" class=3D"m_-7280704993387610058styled-=
by-prettify"> </span><span style=3D"color:#660" class=3D"m_-728070499338761=
0058styled-by-prettify">(</span><span style=3D"color:#000" class=3D"m_-7280=
704993387610058styled-by-prettify">T</span><span style=3D"color:#660" class=
=3D"m_-7280704993387610058styled-by-prettify">::*</span><span style=3D"back=
ground-color:rgb(255,255,0)"><span style=3D"color:#000" class=3D"m_-7280704=
993387610058styled-by-prettify">func</span></span><span style=3D"color:#660=
" class=3D"m_-7280704993387610058styled-by-prettify">)</span><span style=3D=
"color:#000" class=3D"m_-7280704993387610058styled-by-prettify">) {<br>=C2=
=A0=C2=A0=C2=A0 return member_callback<T, <span style=3D"background-colo=
r:rgb(255,255,0)">func</span>>();<br>}<br></span></div></code></div><br>=
Further use cases are metafunctions that depend on a function's signatu=
re and simpler template metaprogramming constructs.<br><br>- Do you think i=
t's valid and fits in C++?<br>- Is there anyone working on similar prop=
osal(s)?</div></blockquote><div><br></div><div>Try searching the archives o=
f this list; this has been suggested several times before.=C2=A0</div></div=
></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;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/CAOfiQq%3DFG50q4NhqY1L41HPSL-ZJ7U%2B%=
3DFZURJyYKobKsSW9NHA%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoote=
r">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAOfiQq%3DF=
G50q4NhqY1L41HPSL-ZJ7U%2B%3DFZURJyYKobKsSW9NHA%40mail.gmail.com</a>.<br />
--047d7b6251a077ae7f0543cf568c--
.