Topic: Proposal to turn non-member function templates for a
Author: Lingxi Li <lilingxi.cs@gmail.com>
Date: Thu, 8 Oct 2015 06:53:00 -0700 (PDT)
Raw View
------=_Part_1084_1534643279.1444312380708
Content-Type: multipart/alternative;
boundary="----=_Part_1085_1091840288.1444312380709"
------=_Part_1085_1091840288.1444312380709
Content-Type: text/plain; charset=UTF-8
Currently, in the standard library, when some functionality for a class
template is impossible or unsuitable to be implemented as a member
function, it is implemented as a non-member function template. For example,
std::vector has the following non-member function template defined for it:
template <class T, class Allocator>
bool operator< (const vector<T, Allocator>& x, const vector<T, Allocator>& y
);
However, functionality implemented in this manner is not accessible via
std::reference_wrapper. For example:
#include <functional>
#include <iostream>
#include <vector>
int main() {
//std::vector<int> a, b; // Oops.
int a = 0, b = 0;
auto refa = std::ref(a);
auto refb = std::ref(b);
std::cout << (refa < refb);
}
The program compiles fine when a and b are of type int, but does not when
they are of type std::vector<int>, despite the fact that
std::reference_wrapper<std::vector<int>> is implicitly convertible to
std::vector<int>& for which an overloaded operator< is defined.
This phenomenon turns out to be caused by the template nature of the
non-member functions. According to N4296
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf> 14.8.1
[temp.arg.explicit] para. 6
> Implicit conversions (Clause 4) will be performed on a function argument
> to convert it to the type of the corresponding function parameter if the
> parameter type contains no template-parameters that participate in template
> argument deduction.
To remedy this issue, I propose to define the non-member functions inline
as friends of their corresponding class template. Functions defined in this
manner are non-templates, and are accessible via std::reference_wrapper.
For example, the overloaded operator< for std::vector could be revised as
template <class T, class Allocator = allocator<T>>
class vector {
...
friend bool operator< (const vector& x, const vector& y) { ... }
};
--
---
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_1085_1091840288.1444312380709
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><font face=3D"Arial, sans-serif" style=3D"font-size: 13.33=
33px;">Currently, in the standard library, when some functionality for a cl=
ass template is impossible or unsuitable to be implemented as a member func=
tion, it is implemented as a non-member function template. For example,=C2=
=A0</font><span style=3D"font-size: 13.3333px; background-color: rgb(238, 2=
38, 238);"><font face=3D"courier new, monospace">std::vector</font></span><=
font face=3D"Arial, sans-serif" style=3D"font-size: 13.3333px;">=C2=A0has t=
he following non-member function template defined for it:</font><div><font =
face=3D"Arial, sans-serif"><span style=3D"font-size: 13.3333px;"><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"prettypri=
nt"><div class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">template</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify"><</span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
class</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> T</s=
pan><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">class</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;"=
class=3D"styled-by-prettify">Allocator</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">bool</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">operator</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
><</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span =
style=3D"color: #008;" class=3D"styled-by-prettify">const</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> vector</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"> </span><span style=3D"color: #606;" class=3D"styled-by=
-prettify">Allocator</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">>&</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> x</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #008;" class=3D"styled-by-prettify">const</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"> vector</span><span st=
yle=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;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #606;" class=3D"sty=
led-by-prettify">Allocator</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">>&</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> y</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">);</span></div></code></div><div><font face=3D"Arial, sans-serif" st=
yle=3D"font-size: 13.3333px;">However, functionality implemented in this ma=
nner is not accessible via=C2=A0</font><span style=3D"font-family: Arial, H=
elvetica, sans-serif; font-size: 13.3333px; background-color: rgb(238, 238,=
238);"><font face=3D"courier new, monospace">std::reference_wrapper</font>=
</span><font face=3D"Arial, sans-serif" style=3D"font-size: 13.3333px;">. F=
or example:</font></div></span></font></div><div><font face=3D"Arial, sans-=
serif"><span style=3D"font-size: 13.3333px;"><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: #800;" class=3D"styled-by-prettify">#in=
clude</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #080;" class=3D"styled-by-prettify"><functional=
></span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></=
span><span style=3D"color: #800;" class=3D"styled-by-prettify">#include</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span =
style=3D"color: #080;" class=3D"styled-by-prettify"><iostream></span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span =
style=3D"color: #800;" class=3D"styled-by-prettify">#include</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #080;" class=3D"styled-by-prettify"><vector></span><span style=
=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;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br>=C2=A0 </span><span style=3D"color: #800;" class=3D"styled-by-=
prettify">//std::vector<int> a, b; =C2=A0// Oops.</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">int</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> a </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #066;" class=3D"st=
yled-by-prettify">0</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
b </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span =
style=3D"color: #066;" class=3D"styled-by-prettify">0</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #=
008;" class=3D"styled-by-prettify">auto</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> refa </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> std</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">::</span><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">ref</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify">a</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">);</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">auto</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> refb </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> std</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">::</span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">ref</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">);</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 std</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify">cout </span><span st=
yle=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: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify">refa </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify"><</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> refb</span><span style=3D"color: #660;" class=3D"styled=
-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></div></code></div><div><font face=3D"Arial, sans-serif" style=3D"f=
ont-size: 13.3333px;">The program compiles fine when=C2=A0</font><span styl=
e=3D"font-family: Arial, Helvetica, sans-serif; font-size: 13.3333px; backg=
round-color: rgb(238, 238, 238);"><font face=3D"courier new, monospace">a</=
font></span><font face=3D"Arial, sans-serif" style=3D"font-size: 13.3333px;=
">=C2=A0and=C2=A0</font><span style=3D"font-family: Arial, Helvetica, sans-=
serif; font-size: 13.3333px; background-color: rgb(238, 238, 238);"><font f=
ace=3D"courier new, monospace">b</font></span><font face=3D"Arial, sans-ser=
if" style=3D"font-size: 13.3333px;">=C2=A0are of type=C2=A0</font><span sty=
le=3D"font-family: Arial, Helvetica, sans-serif; font-size: 13.3333px; back=
ground-color: rgb(238, 238, 238);"><font face=3D"courier new, monospace">in=
t</font></span><font face=3D"Arial, sans-serif" style=3D"font-size: 13.3333=
px;">, but does not when they are of type=C2=A0</font><span style=3D"font-f=
amily: Arial, Helvetica, sans-serif; font-size: 13.3333px; background-color=
: rgb(238, 238, 238);"><font face=3D"courier new, monospace">std::vector<=
;int></font></span><font face=3D"Arial, sans-serif" style=3D"font-size: =
13.3333px;">,=C2=A0despite the fact that=C2=A0</font><span style=3D"font-fa=
mily: Arial, Helvetica, sans-serif; font-size: 13.3333px; background-color:=
rgb(238, 238, 238);"><font face=3D"courier new, monospace">std::reference_=
wrapper<std::<wbr>vector<int>></font></span><font face=3D"Arial=
, sans-serif" style=3D"font-size: 13.3333px;">=C2=A0is implicitly convertib=
le to=C2=A0</font><span style=3D"font-family: Arial, Helvetica, sans-serif;=
font-size: 13.3333px; background-color: rgb(238, 238, 238);"><font face=3D=
"courier new, monospace">std::vector<int>&</font></span><font fac=
e=3D"Arial, sans-serif" style=3D"font-size: 13.3333px;">=C2=A0for which an =
overloaded=C2=A0</font><span style=3D"font-family: Arial, Helvetica, sans-s=
erif; font-size: 13.3333px; background-color: rgb(238, 238, 238);"><font fa=
ce=3D"courier new, monospace">operator<</font></span><font face=3D"Arial=
, sans-serif" style=3D"font-size: 13.3333px;">=C2=A0is defined.</font></div=
><div><span style=3D"font-size: 13.3333px;">This phenomenon turns out to be=
caused by the template nature of the non-member functions. According to=C2=
=A0</span><a href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/201=
4/n4296.pdf" target=3D"_blank" rel=3D"nofollow" style=3D"cursor: pointer; f=
ont-size: 13.3333px;">N4296</a><span style=3D"font-size: 13.3333px;">=C2=A0=
14.8.1 [temp.arg.explicit] para. 6</span></div></span></font></div><blockqu=
ote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; border-left-w=
idth: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid;=
padding-left: 1ex;"><font face=3D"Arial, sans-serif"><span style=3D"font-s=
ize: 13.3333px;">Implicit conversions (Clause 4) will be performed on a fun=
ction argument to convert it to the type of the corresponding function para=
meter if the parameter type contains no template-parameters that participat=
e in template argument deduction.</span></font></blockquote><div><font face=
=3D"Arial, sans-serif"><span style=3D"font-size: 13.3333px;">To remedy this=
issue, I propose to d</span></font><font face=3D"Arial, sans-serif" style=
=3D"font-size: 13.3333px;">efine the non-member functions inline as friends=
of their corresponding class template. Functions defined in this manner ar=
e non-templates, and are accessible via=C2=A0</font><span style=3D"font-siz=
e: 13.3333px; background-color: rgb(238, 238, 238);"><font face=3D"courier =
new, monospace">std::reference_wrapper</font></span><font face=3D"Arial, sa=
ns-serif" style=3D"font-size: 13.3333px;">. For example, the overloaded=C2=
=A0</font><span style=3D"font-size: 13.3333px; background-color: rgb(238, 2=
38, 238);"><font face=3D"courier new, monospace">operator<</font></span>=
<font face=3D"Arial, sans-serif" style=3D"font-size: 13.3333px;">=C2=A0for=
=C2=A0</font><span style=3D"font-size: 13.3333px; background-color: rgb(238=
, 238, 238);"><font face=3D"courier new, monospace">std::vector</font></spa=
n><font face=3D"Arial, sans-serif" style=3D"font-size: 13.3333px;">=C2=A0co=
uld be revised as</font></div><div><font face=3D"Arial, sans-serif"><span s=
tyle=3D"font-size: 13.3333px;"><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"subprettyprint">=
<span style=3D"color: #008;" class=3D"styled-by-prettify">template</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">class</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> T</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">class</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">Allo=
cator</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> allocator</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify"><</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify">T</span><span style=3D"colo=
r: #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">class</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> vector </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>=C2=A0 </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">...</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br>=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">friend</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">boo=
l</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><=
span style=3D"color: #008;" class=3D"styled-by-prettify">operator</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify"><</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #008;=
" class=3D"styled-by-prettify">const</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> vector</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">&</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> x</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">const</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> vector</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">&</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> y</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 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-pretti=
fy"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">};</span></div></cod=
e></div><div><br></div></span></font></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_1085_1091840288.1444312380709--
------=_Part_1084_1534643279.1444312380708--
.