C++ 函数重载:空参数列表与参数包
GCC、Clang和MSVC都使用#1 然而,标准中的偏序规则规定: 如果与Pi相对应的参数声明是函数参数包,则其声明器id的类型将与a的参数类型列表中的每个剩余参数类型进行比较。每次比较都会推断由函数参数包展开的模板参数包中后续位置的模板参数。在偏序期间,如果Ai最初是一个函数参数包:C++ 函数重载:空参数列表与参数包,c++,templates,language-lawyer,variadic-templates,overload-resolution,C++,Templates,Language Lawyer,Variadic Templates,Overload Resolution,GCC、Clang和MSVC都使用#1 然而,标准中的偏序规则规定: 如果与Pi相对应的参数声明是函数参数包,则其声明器id的类型将与a的参数类型列表中的每个剩余参数类型进行比较。每次比较都会推断由函数参数包展开的模板参数包中后续位置的模板参数。在偏序期间,如果Ai最初是一个函数参数包: (10.1)如果p不包含与Ai对应的函数参数类型,则忽略Ai (10.2)否则,如果Pi不是函数参数包,则模板参数推断失败。 当我们从#2推导出#1时,T,Args…作为A,T作为p,p不包含对应于Args
- (10.1)如果p不包含与Ai对应的函数参数类型,则忽略Ai强>
- (10.2)否则,如果Pi不是函数参数包,则模板参数推断失败。
T,Args…
作为A,T
作为p,p不包含对应于Args…
的模板参数<代码>参数…被忽略,因此可以成功地从#2推导出#1
然后从#1中推断#2,将T
作为A,将T,Args…
作为p,也成功地得到T=T,Args…={}
因此,根据偏序规则,当调用
call(10)
时,编译器应该给出不明确的错误,但实际上所有编译器都调用了#1,这是为什么?编译器是正确的<代码>#1比#2
更专业
偏序模板参数包的规则在中指定: 使用结果类型
p
和A
,然后按如下方式进行扣除
在[温度扣除类型]中描述。如果P
是一个功能参数包,
参数模板的每个剩余参数类型的类型A
与函数的声明器id的类型P
进行比较
参数包。每次比较都会推断出
模板参数包中的后续位置由
函数参数包。类似地,如果A
是从
函数参数包,它与每个剩余参数进行比较
参数模板的类型。如果对给定的
类型,则参数模板中的类型被视为至少
与参数模板中的类型一样专用
当参数模板为#1
且参数模板为#2
时,将#2
中的声明符idArgs
(这是一种类型)与#1
中的每个剩余参数进行比较(没有)。因此,#2
至少与#1
一样专业化
当参数模板为#2
且参数模板为#1
时,将#2
中的声明符idArgs
(这是一种类型)与#1
中的每个剩余参数进行比较(没有)。因此,#1
至少与#2
一样专业化
看起来模棱两可,对吧?现在我们有了打破僵局的人:
如果在考虑上述因素后,函数模板F
至少为
专用于函数模板G
,反之亦然,如果G
具有
F
没有对应的尾部参数包
参数,并且如果F
没有后续参数包,则
F
比G
更专业
显然,
#1
比#2更专业化,你必须在文本中用单引号转义
,否则它不可见,这对你来说是固定的,但不确定我是否遗漏了一些不是专业化的东西?@奇怪的是不是。这是一个主要的模板。
template <typename T>
void call(T) { //#1
std::cout << "1" << std::endl;
}
template <typename T, typename...Args>
void call(T, Args...) { //#2
std::cout << "2" << std::endl;
}
call(10);