gpt4 book ai didi

c++ - 包含模板参数包的函数模板的部分排序

转载 作者:搜寻专家 更新时间:2023-10-31 01:38:02 26 4
gpt4 key购买 nike

Partial ordering of function templates containing template parameter packs is independent of the number of deduced arguments for those template parameter packs.

template<class...> struct Tuple { };
template< class... Types> void g(Tuple<Types ...>); // #1
template<class T1, class... Types> void g(Tuple<T1, Types ...>); // #2
template<class T1, class... Types> void g(Tuple<T1, Types& ...>); // #3

g(Tuple<>()); // calls #1
g(Tuple<int, float>()); // calls #2
g(Tuple<int, float&>()); // calls #3
g(Tuple<int>()); // calls #3

以上内容转自partial ordering of overload function templates .我不太明白为什么g(Tuple<int>()); // calls #3 .具体来说,为什么不能 #2叫做?以下是我的推理,如有错误请指出:

注意:我会忽略#1 b/c 解释得很好 here

第 1 步:推导和替换以及重载决议得出这些:

  • void(Tuple< int>) [T1 = int, 类型为空] #2
  • void(Tuple< int>) [T1 = int, Types& 为空] #3

第 2 步:转换两个函数模板:

  • void g(Tuple< C1, Pack1...>);
  • void g(Tuple< C2, Pack2&...>);

Step3:这是一个函数调用上下文,类型是函数调用有参数的那些函数参数类型:

  • 从 Tuple 推导 Tuple OK [T1 = C2;类型... = 包装&...]
  • 从 Tuple 推导出 Tuple ) 好吗? [T1 = C1; Types&... 呢?可以从Pack1推导出来吗...?此处引用被删除了吗?]

3) If P is a reference type, the type referred to by P is used for deduction.This seems fine.

If P has one of the forms that include a template parameter list < T> or < I>, then each element Pi of that template argument list is matched against the corresponding template argument Ai of its A. If the last Pi is a pack expansion, then its pattern is compared against each remaining argument in the template argument list of A. A trailing parameter pack that is not otherwise deduced, is deduced to an empty parameter pack.

Step4:如果最后一步正确。那么这意味着#3 并不比#2 更专业。因此对于应该解析到哪个函数模板是不明确的。

更新:我想我误解了上面的相关引述。当我们将 P 中的模板参数与 A 中的模板参数进行匹配时,它们是逐字匹配的,这意味着当我们匹配时,对函数调用参数和参数所做的所有转换和分析都不会再次应用P/A中的模板参数/参数(实际上是函数调用参数/参数)。然后它会在上面的第 3 步 中推断出 Tuple< T1, Types&...> 失败。来自 Tuple< C1, Pack1...>) .所以#3更专业。

最佳答案

重载决议的第一步是找到所有候选者。来电g(Tuple<int>()) , 有三个可行的候选者:

g(Tuple<int>); // #1: [Types = {int}]
g(Tuple<int>); // #2: [T1 = int, Types = {}]
g(Tuple<int>); // #3: [T1 = int, Types = {}]

从转换序列的角度来看,这三个都是同样可行的候选者(因为,当然,它们都采用相同的参数,即输入的完全匹配)。它们都是函数模板特化,因此我们也无法在此基础上进行区分。

所以我们只剩下函数模板偏序了。我们为每个重载合成类型,并尝试使用我们合成的类型针对每个其他重载执行模板推导。更简单的比较是 (1) vs (2) 和 (1) vs (3)。在那里,我们有 [temp.deduct.partial]:

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

自从我们转换Types...进入UniqA... ,第一个参数为T1 , 类型推导失败。这使得 (2) 和 (3) 都比 (1) 更专业。所以现在我们比较 (2) 和 (3)。

首先,我们可以从 (3) 推导出 (2) 吗?

template <class T1, class... Types> void g(Tuple<T1, Types...> );

g(Tuple<Uniq3, Uniq3Pack&...>());

当然,没问题T1 == Uniq3Types... == Uniq3Pack&... .接下来,我们尝试另一个方向:

template <class T1, class... Types> void g(Tuple<T1, Types&...> );

g(Tuple<Uniq2, Uniq2Pack...>());

这失败了,因为 Uniq2Pack不是一组引用类型和 Types&...是。由于演绎只在一个方向上成功,这使得 (3) 成为更专业的重载。

因为它是最后一位,所以 (3) 是最可行的候选者。这似乎违反直觉,因为我们实际上并没有使用引用类型调用它 - 但它仍然是最佳选择。

关于c++ - 包含模板参数包的函数模板的部分排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33426038/

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