聚合模板别名推导指南怎么写?
How to write deduction guidelines for aliases of aggregate templates?
使用 C++20,可以为别名模板生成推导指南(请参阅 https://en.cppreference.com/w/cpp/language/class_template_argument_deduction 的“别名模板推导”部分)。然而,我无法让它们使用聚合初始化语法。在这种情况下,似乎没有生成别名的扣除指南。
看这个例子:
#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];
}
我曾尝试编写演绎指南,但每次都会遇到编译器错误。
template <typename T, typename ... U>
mytype(T, U...) -> mytype<1+sizeof...(U)>; // Compiler error
以及我能想到的任何其他指南。
是否可以自动推导数组别名的大小?
我正在使用 GCC 10.2
Is it even possible to have the size of the array alias automatically deduced?
我相信通过符合标准的实施应该是可能的。您不需要(也不能)添加任何更多指南。
但是,GCC 实现的 a different set of rules 比标准指定的要多:
This implementation differs from [the specification] in two significant ways:
1) We include all template parameters of A, not just some.
2) The added constraint is same_type instead of deducible.
实施者认为“这种简化对于实际使用应该具有相同的效果”。但显然情况并非如此:此实现在您的情况下无法正常工作 ICEs in some other cases.
作为参考,我将尝试遵循标准并展示如何生成 mytype
的指南。
我们有这个别名模板声明(别名模板在标准中称为A
):
template <size_t N>
using mytype = std::array<int, N>;
以及来自标准库 ([array.cons]) 的推导指南:
template<class T, class... U>
array(T, U...) -> array<T, 1 + sizeof...(U)>;
首先根据推导指南([over.match.class.deduct]/1)生成函数模板(标准中称为f
):
template<class T, class... U>
auto f(T, U...) -> array<T, 1 + sizeof...(U)>;
然后,根据 [over.match.class.deduct]/2:
the template arguments of the return type of f
are deduced from the defining-type-id of A
according to the process in [temp.deduct.type] with the exception that deduction does not fail if not all template arguments are deduced.
也就是说,我们从std::array<int, N>
推导出array<T, 1 + sizeof...(U)>
中的模板参数。在这个过程中,T
被推导为int
; U
不可推导,所以保持原样。
推导结果代入函数模板,得到:
template<class T, class... U>
auto g(int, U...) -> array<int, 1 + sizeof...(U)>;
然后,我们生成一个函数模板f'
。 f'
与 g
具有相同的 return 类型和函数参数类型。 (如果 f
有特殊属性,它们被 f'
继承。)但值得注意的是, f'
的模板参数列表由 ([over.match.class.deduct]/(2.2),强调我的):
all the template parameters of A
(including their default template arguments) that appear in the above deductions or (recursively) in their default template arguments, followed by the template parameters of f
that were not deduced (including their default template arguments), otherwise f'
is not a function template.
由于N
没有出现在推导中,所以不包含在模板参数列表中(这是GCC与标准不同的地方)。
此外,f'
有一个约束条件 ([over.match.class.deduct]/(2.3)):
that is satisfied if and only if the arguments of A
are deducible (see below) from the return type.
因此,按照标准,生成的函数模板是这样的:
template<class... U>
requires deducible<array<int, 1 + sizeof...(U)>>
auto f'(int, U...) -> array<int, 1 + sizeof...(U)>;
显然,根据本指南可以推导出大小为1 + sizeof...(U)
。
下一步,我们看看deducible
是如何定义的
The arguments of a template A
are said to be deducible from a type T
if, given a class template
template <typename> class AA;
with a single partial specialization whose template parameter list is that of A
and whose template argument list is a specialization of A
with the template argument list of A
([temp.dep.type]), AA<T>
matches the partial specialization.
在我们的例子中,部分专业化将是:
template <size_t N> class AA<mytype<N>> {};
因此 deducible
可以声明为:
template <class T> concept deducible = requires { sizeof(AA<T>); };
由于 N
可从 1 + sizeof...(U)
推导出来,array<int, 1 + sizeof...(U)>
始终是 mytype<N>
的有效匹配(a.k.a。std::arrray<int, N>
),因此总是满足约束 deducible<array<int, 1 + sizeof...(U)>>
。
因此,根据标准,生成的指南是可行的,可以推导出大小。
相比之下,GCC 生成:
template<class... U, size_t N>
requires same_type<array<int, 1 + sizeof...(U)>, mytype<N>>
auto f_(int, U...) -> array<int, 1 + sizeof...(U)>;
...无法推导出 N
.
使用 C++20,可以为别名模板生成推导指南(请参阅 https://en.cppreference.com/w/cpp/language/class_template_argument_deduction 的“别名模板推导”部分)。然而,我无法让它们使用聚合初始化语法。在这种情况下,似乎没有生成别名的扣除指南。
看这个例子:
#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];
}
我曾尝试编写演绎指南,但每次都会遇到编译器错误。
template <typename T, typename ... U>
mytype(T, U...) -> mytype<1+sizeof...(U)>; // Compiler error
以及我能想到的任何其他指南。
是否可以自动推导数组别名的大小?
我正在使用 GCC 10.2
Is it even possible to have the size of the array alias automatically deduced?
我相信通过符合标准的实施应该是可能的。您不需要(也不能)添加任何更多指南。
但是,GCC 实现的 a different set of rules 比标准指定的要多:
This implementation differs from [the specification] in two significant ways: 1) We include all template parameters of A, not just some. 2) The added constraint is same_type instead of deducible.
实施者认为“这种简化对于实际使用应该具有相同的效果”。但显然情况并非如此:此实现在您的情况下无法正常工作 ICEs in some other cases.
作为参考,我将尝试遵循标准并展示如何生成 mytype
的指南。
我们有这个别名模板声明(别名模板在标准中称为A
):
template <size_t N>
using mytype = std::array<int, N>;
以及来自标准库 ([array.cons]) 的推导指南:
template<class T, class... U>
array(T, U...) -> array<T, 1 + sizeof...(U)>;
首先根据推导指南([over.match.class.deduct]/1)生成函数模板(标准中称为f
):
template<class T, class... U>
auto f(T, U...) -> array<T, 1 + sizeof...(U)>;
然后,根据 [over.match.class.deduct]/2:
the template arguments of the return type of
f
are deduced from the defining-type-id ofA
according to the process in [temp.deduct.type] with the exception that deduction does not fail if not all template arguments are deduced.
也就是说,我们从std::array<int, N>
推导出array<T, 1 + sizeof...(U)>
中的模板参数。在这个过程中,T
被推导为int
; U
不可推导,所以保持原样。
推导结果代入函数模板,得到:
template<class T, class... U>
auto g(int, U...) -> array<int, 1 + sizeof...(U)>;
然后,我们生成一个函数模板f'
。 f'
与 g
具有相同的 return 类型和函数参数类型。 (如果 f
有特殊属性,它们被 f'
继承。)但值得注意的是, f'
的模板参数列表由 ([over.match.class.deduct]/(2.2),强调我的):
all the template parameters of
A
(including their default template arguments) that appear in the above deductions or (recursively) in their default template arguments, followed by the template parameters off
that were not deduced (including their default template arguments), otherwisef'
is not a function template.
由于N
没有出现在推导中,所以不包含在模板参数列表中(这是GCC与标准不同的地方)。
此外,f'
有一个约束条件 ([over.match.class.deduct]/(2.3)):
that is satisfied if and only if the arguments of
A
are deducible (see below) from the return type.
因此,按照标准,生成的函数模板是这样的:
template<class... U>
requires deducible<array<int, 1 + sizeof...(U)>>
auto f'(int, U...) -> array<int, 1 + sizeof...(U)>;
显然,根据本指南可以推导出大小为1 + sizeof...(U)
。
下一步,我们看看deducible
是如何定义的
The arguments of a template
A
are said to be deducible from a typeT
if, given a class templatetemplate <typename> class AA;
with a single partial specialization whose template parameter list is that of
A
and whose template argument list is a specialization ofA
with the template argument list ofA
([temp.dep.type]),AA<T>
matches the partial specialization.
在我们的例子中,部分专业化将是:
template <size_t N> class AA<mytype<N>> {};
因此 deducible
可以声明为:
template <class T> concept deducible = requires { sizeof(AA<T>); };
由于 N
可从 1 + sizeof...(U)
推导出来,array<int, 1 + sizeof...(U)>
始终是 mytype<N>
的有效匹配(a.k.a。std::arrray<int, N>
),因此总是满足约束 deducible<array<int, 1 + sizeof...(U)>>
。
因此,根据标准,生成的指南是可行的,可以推导出大小。
相比之下,GCC 生成:
template<class... U, size_t N>
requires same_type<array<int, 1 + sizeof...(U)>, mytype<N>>
auto f_(int, U...) -> array<int, 1 + sizeof...(U)>;
...无法推导出 N
.