gpt4 book ai didi

c++ - 如何编写聚合模板别名的推导指南?

转载 作者:行者123 更新时间:2023-12-03 10:03:33 26 4
gpt4 key购买 nike

使用 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.


也就是说,我们推导出 array<T, 1 + sizeof...(U)> 中的模板参数来自 std::array<int, N> .在这个过程中, T推导出为 int ; U不可推导,因此保持原样。
将推导的结果代入函数模板,得到:
template<class T, class... U>
auto g(int, U...) -> array<int, 1 + sizeof...(U)>;
然后,我们生成一个函数模板 f' . f'具有与 g 相同的返回类型和函数参数类型. (如果 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被定义为。
[over.match.class.deduct]/3 :

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> 的有效匹配项(又名 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++ - 如何编写聚合模板别名的推导指南?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64939408/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com