Topic: Class template argument deduction from class static functions


Author: Anthony Hall <anthrond@gmail.com>
Date: Sat, 3 Dec 2016 22:37:47 -0800 (PST)
Raw View
------=_Part_451_364012279.1480833467543
Content-Type: multipart/alternative;
 boundary="----=_Part_452_751666331.1480833467544"

------=_Part_452_751666331.1480833467544
Content-Type: text/plain; charset=UTF-8

What if class template argument deduction, which we've gained in C++17,
were extended to static class functions, not just constructors?  For a
personal project, I'm trying to enable this sort of deduction for
constructors of a class wherever I can, but I've realized that for some
ways of constructing a class instance I'd probably prefer to use the named
constructor idiom, where a static class function returns an instance of the
class by value.  However, it occurs to me that I would then lose the
convenience of the new class template argument deduction feature, since to
my knowledge it has not been extended to work for static class functions as
well.

So, for example, as things are now in the working draft of C++17, to use
this named constructor, I would have do something like the following:

template< typename T, size_t N >
struct Vector {
    std::array< T, N > components;


    template< typename ...S >

    requires sizeof...(S) == N
        && (std::is_convertible_v< S, T > && ...)
        // ^ (Using Concepts TS to constrain number and types of args,
        // but this is not central to this proposal)
    static Vector fromComponents( S &&...s ) {
        Vector<T, N> v;
        v.components = { std::forward<S>( s )... };
        return v;
    }
    // ...
};

// Here I have to give the template arguments to Vector explicitly, to
specify
// for which specialization of Vector 'fromComponents()' is being called
auto vec = Vector<float, 3>::fromComponents( 0.74f, 0.74f, 0.0f );

It would be nice, however, if a deduction guide could be supplied for
'fromComponents', so that 'vec' could be initialized more simple:

// Proposed deduction guide mechanism for class static functions
template< typename ...S >
Vector::fromComponents( S &&...s ) -> Vector< std::common_type< S... >,
sizeof...(S) >;

// Now, the deduction guide above makes the compiler able to deduce which
// specialization of Vector to use, from the function arguments.
auto vec = Vector::fromComponents( 0.74f, 0.74f, 0.0f );

I haven't given thought yet to how this would work for automatic deduction
guides -- whether and how much sense that would make for static functions.

For now I wanted to know if others think this looks like a useful direction
for extending this feature, and is it something worth proposing for the
standard?  (I realize it's probably too late for c++17, but wondered if it
still looks like something nice for future standards)

P.S. I also just noticed that the example I gave was of a static function
_template_ inside a struct template: it's interesting to me that in such a
case the static function's arguments are being used to deduce the template
arguments for _two_ entities: first the function template arguments
themselves, then those for the surrounding struct.  It makes me wonder if
there are further generalizations of this notion of deducing the template
arguments for one entity from arguments to another entity.  I don't have
any other concrete examples come to mind, but noticing that pattern just
led me to wonder if there's some general abstraction trying to come out of
all this.

--
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/22f8994a-11a8-4ecf-b11d-b8a902e4b9b3%40isocpp.org.

------=_Part_452_751666331.1480833467544
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div>What if class template argument deduction, which we&#=
39;ve gained in C++17, were extended to static class functions, not just co=
nstructors? =C2=A0For a personal project, I&#39;m trying to enable this sor=
t of deduction for constructors of a class wherever I can, but I&#39;ve rea=
lized that for some ways of constructing a class instance I&#39;d probably =
prefer to use the named constructor idiom, where a static class function re=
turns an instance of the class by value. =C2=A0However, it occurs to me tha=
t I would then lose the convenience of the new class template argument dedu=
ction feature, since to my knowledge it has not been extended to work for s=
tatic class functions as well. =C2=A0</div><div><br></div><div>So, for exam=
ple, as things are now in the working draft of C++17, to use this named con=
structor, I would have do something like the following:</div><div><br></div=
><div class=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); =
border-color: rgb(187, 187, 187); border-style: solid; border-width: 1px; w=
ord-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"subprettyp=
rint"><span style=3D"color: #008;" class=3D"styled-by-prettify">template</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><s=
pan 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"colo=
r: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"> size_t N </span><span style=3D"color: #660;"=
 class=3D"styled-by-prettify">&gt;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">struct</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-prett=
ify">Vector</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=
 std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify">array</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> T</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> N </span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">&gt;</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> components</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br><br><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" c=
lass=3D"styled-by-prettify">template</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">&lt;</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-p=
rettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
....</span><span style=3D"color: #000;" class=3D"styled-by-prettify">S </spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0 =C2=A0=
 requires </span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
sizeof</span><span style=3D"color: #660;" class=3D"styled-by-prettify">...(=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify">S</span><s=
pan 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">=3D=3D</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> N<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">&amp;&amp;</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify">std</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify">is_convertible_v</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> S</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> T </span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>&gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">&amp;&amp;</sp=
an><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 =C2=A0 =C2=
=A0 </span><span style=3D"color: #800;" class=3D"styled-by-prettify">// ^ (=
Using Concepts TS to constrain number and types of args,</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 </span><span style=3D"color: #800;" class=3D"styled-by-prettify">// but=
 this is not central to this proposal)</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: =
#008;" class=3D"styled-by-prettify">static</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" class=
=3D"styled-by-prettify">Vector</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> fromComponents</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> S </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">&amp;&amp;...</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify">s </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">)</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: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 </span><span style=3D"color: #606;" class=3D"styled-by-prettify"=
>Vector</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt=
;</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 styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> N</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">&gt;</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> v</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 v</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify">components </span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> std</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">forward=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify">S</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">&gt;(</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> s </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">)...</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">};</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">return</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> v</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #800;" clas=
s=3D"styled-by-prettify">// ...</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-pre=
ttify"><br><br></span><span style=3D"color: #800;" class=3D"styled-by-prett=
ify">// Here I have to give the template arguments to Vector explicitly, to=
 specify</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><b=
r></span><span style=3D"color: #800;" class=3D"styled-by-prettify">// for w=
hich specialization of Vector &#39;fromComponents()&#39; is being called </=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><=
span style=3D"color: #008;" class=3D"styled-by-prettify">auto</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> vec </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;=
" class=3D"styled-by-prettify">Vector</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">&lt;</span><span style=3D"color: #008;" class=3D=
"styled-by-prettify">float</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #066;" class=3D"styled-by-prettify">3<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;::</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify">fromComponents<=
/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: #066;" class=3D"styled-by-prettify">0.74f</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </span><span style=3D"color: #066;" class=
=3D"styled-by-prettify">0.74f</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #066;" class=3D"styled-by-prettify"=
>0.0f</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">);</span></div=
></code></div><div><br></div><div>It would be nice, however, if a deduction=
 guide could be supplied for &#39;fromComponents&#39;, so that &#39;vec&#39=
; could be initialized more simple:</div><div><br></div><div class=3D"prett=
yprint" style=3D"background-color: rgb(250, 250, 250); border-color: rgb(18=
7, 187, 187); border-style: solid; border-width: 1px; word-wrap: break-word=
;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D=
"color: #800;" class=3D"styled-by-prettify">// Proposed deduction guide mec=
hanism for class static functions</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">template</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">&lt;</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"> =
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">...</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify">S </span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color=
: #606;" class=3D"styled-by-prettify">Vector</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify">fromComponents</span><span style=3D"color: #660;"=
 class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> S </span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">&amp;&amp;...</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify">s </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
 </span><span style=3D"color: #660;" class=3D"styled-by-prettify">-&gt;</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span =
style=3D"color: #606;" class=3D"styled-by-prettify">Vector</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> std</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify">common_type</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> S</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">...</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
&gt;,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">sizeof</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">...(</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">S</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">&gt;;</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br><br></span><span style=3D"color: #800;" class=3D"sty=
led-by-prettify">// Now, the deduction guide above makes the compiler able =
to deduce which</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"><br></span><span style=3D"color: #800;" class=3D"styled-by-prettify">/=
/ specialization of Vector to use, from the function arguments. </span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"><br></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"> vec </span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" class=3D=
"styled-by-prettify">Vector</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify">fromComponents</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: #066;" class=3D"styled-by-prettify">0.74f=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #066;" class=3D"styled-by-prettify">0.74f</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </span><span style=3D"color: #066;" class=
=3D"styled-by-prettify">0.0f</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">);</span></div></code></div><div><br></div><div>I haven&#39;t give=
n thought yet to how this would work for automatic deduction guides -- whet=
her and how much sense that would make for static functions.<br><br>For now=
 I wanted to know if others think this looks like a useful direction for ex=
tending this feature, and is it something worth proposing for the standard?=
 =C2=A0(I realize it&#39;s probably too late for c++17, but wondered if it =
still looks like something nice for future standards)</div><div><br></div><=
div>P.S. I also just noticed that the example I gave was of a static functi=
on _template_ inside a struct template: it&#39;s interesting to me that in =
such a case the static function&#39;s arguments are being used to deduce th=
e template arguments for _two_ entities: first the function template argume=
nts themselves, then those for the surrounding struct. =C2=A0It makes me wo=
nder if there are further generalizations of this notion of deducing the te=
mplate arguments for one entity from arguments to another entity. =C2=A0I d=
on&#39;t have any other concrete examples come to mind, but noticing that p=
attern just led me to wonder if there&#39;s some general abstraction trying=
 to come out of all this.</div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/22f8994a-11a8-4ecf-b11d-b8a902e4b9b3%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/22f8994a-11a8-4ecf-b11d-b8a902e4b9b3=
%40isocpp.org</a>.<br />

------=_Part_452_751666331.1480833467544--

------=_Part_451_364012279.1480833467543--

.