With C++20, it is possible to have deduction guidelines generated for an alias template (See section "Deduction for alias templates" at https://en.cppreference.com/w/cpp/language/class_template_argument_deduction). Yet, I could not make them work with aggregate initialization syntax. It looks like in this case the deduction guidelines for the alias is not generated.
See this example:
#include <array>
template <size_t N>
using mytype = std::array<int, N>;
// Deduction guideline ???
int main() {
// mytype error_object = {1, 4, 7}; // ERROR
mytype<3> object = {1, 4, 7}; // OK, but I have to manually specify the size.
return object[0];
}
I have tried writing deduction guidelines but I get compiler errors every time.
template <typename T, typename ... U>
mytype(T, U...) -> mytype<1+sizeof...(U)>; // Compiler error
and any other guideline I could think of.
Is it even possible to have the size of the array alias automatically deduced?
I am using GCC 10.2
I believe that it should be possible with a standard-conforming implementation. You needn't (and can't) add any more guides.
However, GCC implements a different set of rules than what the standard specifies:
The implementer believed that "this simplification should have the same effect for real uses". But apparently this is not the case: this implementation fails to work in your case and ICEs in some other cases.
For the reference, I'll try to follow the standard and show how the guide for
mytype
is generated.We have this alias template declaration (the alias template is called
A
in the standard):and this deduction guide from the standard library ([array.cons]):
First, a function template (called
f
in the standard) is generated from the deduction guide ([over.match.class.deduct]/1):Then, per [over.match.class.deduct]/2:
That is, we deduce the template arguments in
array<T, 1 + sizeof...(U)>
fromstd::array<int, N>
. In this process,T
is deduced to beint
;U
is not deducible, so it is left as-is.The result of deduction is substituted into the function template, resulting in:
Then, we generate a function template
f'
.f'
has the same return type and function parameter types asg
. (Iff
has special properties, they are inherited byf'
.) But notably, the template parameter list off'
consists of ([over.match.class.deduct]/(2.2), emphasis mine):Since
N
does not appear in the deduction, it is not included in the template parameter list (this is where GCC differs from the standard).Additionally,
f'
has a constraint ([over.match.class.deduct]/(2.3)):Therefore, according to the standard, the generated function template looks like:
Clearly, the size can be deduced as
1 + sizeof...(U)
according to this guide.In the next step, let's see how
deducible
is defined.[over.match.class.deduct]/3:
In our case, the partial specialization would be:
So
deducible
can be declared as:Since
N
is deducible from1 + sizeof...(U)
,array<int, 1 + sizeof...(U)>
is always a valid match formytype<N>
(a.k.a.std::arrray<int, N>
), and thus the constraintdeducible<array<int, 1 + sizeof...(U)>>
is always satisfied.Therefore, according to the standard, the generated guide is viable and can deduce the size.
In comparison, GCC generates:
... which is not able to deduce
N
.