c++ - 当参数是函数参数包时,在部分排序期间推导模板参数

标签 c++ templates c++11 variadic-templates overload-resolution

N4527 14.8.2.4 [temp.deduct.partial]

3 The types used to determine the ordering depend on the context in which the partial ordering is done:

(3.1) — In the context of a function call, the types used are those function parameter types for which the function call has arguments.

(3.2) — In the context of a call to a conversion function, the return types of the conversion function templates are used.

(3.3) — In other contexts (14.5.6.2) the function template’s function type is used.

4 Each type nominated above from the parameter template and the corresponding type from the argument template are used as the types of P and A.

8 If A was transformed from a function parameter pack and P is not a parameter pack, type deduction fails. Otherwise, using the resulting types P and A, the deduction is then done as described in 14.8.2.5. If P is a function parameter pack, the type A of each remaining parameter type of the argument template is compared with the type P of the declarator-id of the function parameter pack. Each comparison deduces template arguments for subsequent positions in the template parameter packs expanded by the function parameter pack. If deduction succeeds for a given type, the type from the argument template is considered to be at least as specialized as the type from the parameter template. [ Example:

template<class... Args>           void f(Args... args);        // #1
template<class T1, class... Args> void f(T1 a1, Args... args); // #2
template<class T1, class T2>      void f(T1 a1, T2 a2);        // #3

f();        // calls #1
f(1, 2, 3); // calls #2
f(1, 2);    // calls #3; non-variadic template #3 is more
            // specialized than the variadic templates #1 and #2

为什么 f(1, 2, 3); 调用 #2?

我需要更多详细信息,包括:

1 是哪个语境?

2 转化的from是什么?
比如#1 的转换形式是 void (U) , void (U...) 还是其他形式?(U 表示唯一类型)

14.5.6.2 [temp.func.order]/p3

To produce the transformed template, for each type, non-type, or template template parameter (including template parameter packs (14.5.3) thereof) synthesize a unique type, value, or class template respectively and substitute it for each occurrence of that parameter in the function type of the template.

3 推导中使用的PA有哪些类型?例如

template <class T> void f(T);
int a = 1;
f(a);//P = T, A = int

最佳答案

Why f(1, 2, 3); calls #2?

你的问题有很多问题(请每个问题一个问题!),所以我会坚持那个问题。首先,我们执行模板推导。 #3 失败,但 #1 和 #2 成功:

template<class... Args>
void f(Args... args);        // #1, with Args = {int, int, int}
template<class T1, class... Args> 
void f(T1 a1, Args... args); // #2, with T1 = int, Args = {int, int}

这两个函数的值都采用三个 int,因此重载决议中的所有正常决胜局都无法解决歧义。所以我们到了最后一个:

Given these definitions, a viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then
— [...]
F1 and F2 are function template specializations, and the function template for F1 is more specialized than the template for F2 according to the partial ordering rules described in 14.5.6.2.

规则是:

第一步:综合类型[temp.func.order]:

To produce the transformed template, for each type, non-type, or template template parameter (including template parameter packs (14.5.3) thereof) synthesize a unique type, value, or class template respectively and substitute it for each occurrence of that parameter in the function type of the template.

所以我们有:

void f(Pack1... args);         // #1
void f(U2 a1, Pack2... args);  // #2

第 2 步:按照 [temp.deduct.partial] 中的描述执行扣除。我们所在的上下文是函数调用,因此我们使用函数调用具有参数的类型。

首先,我们尝试从#1 推导出#2。也就是说,我们尝试将 (T1, Args...) 与 (Pack1...) 进行匹配。第一部分是 P = T1, A = Pack1...。我们有:

If A was transformed from a function parameter pack and P is not a parameter pack, type deduction fails.

因此从#1 推导#2 失败,因此参数 Args... 至少不像 T1, Args... 那样专门化。

接下来,我们尝试从#2 推导出#1。也就是说,我们尝试将 (Args...)(U2, Pack2...) 进行匹配。成功了,所以 T1, Args... 至少和 Args... 一样专业。

由于#2 至少与#1 一样专业,而#1 至少不如#2 专业,我们可以说#2 更专业:

Function template F is at least as specialized as function template G if, for each pair of types used to determine the ordering, the type from F is at least as specialized as the type from G. F is more specialized than G if F is at least as specialized as G and G is not at least as specialized as F.

首选更专业的模板,因此我们调用#2。

关于c++ - 当参数是函数参数包时,在部分排序期间推导模板参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32373979/

相关文章:

c++ - 在 Linux 上静态链接库

c++ - 模板类的内部类可以是非模板类吗?

c++ - 在 C++ 中检查 double 是否等于负无穷大的最佳方法

c++ - 错误:请求从 ‘Mstream’转换为非标量类型 ‘std::string {aka std::basic_string<char>}’

c++ - Rcpp-使用优化功能

c++ - 确保 move 构造函数存在时永远不会调用复制构造函数

c++ - 使用浮点坐标绘制poly()

python - Django 字符串索引超出范围

php - Symfony2 Twig 扩展

c++ - std::unique_lock 和 std::condition_variable 如何工作