Class template argument deduction from class static functions

81 views
Skip to first unread message

Anthony Hall

unread,
Dec 4, 2016, 1:37:47 AM12/4/16
to ISO C++ Standard - Future Proposals
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.

Daniel Boles

unread,
Dec 4, 2016, 8:02:08 AM12/4/16
to std-pr...@isocpp.org
Interesting question, but I suspect in this case, most people just use
a free "make" function (probably friended) and forget about it. That
should allow all the deduction you could want, right? Sure, it's not as
tightly coupled to the class, but some would argue that's a good thing.
Reply all
Reply to author
Forward
0 new messages