考虑以下代码段:
template<typename T, template<typename, typename ...> class A, typename ... Ts>
int a(A<T, Ts...> arg){
return 1; // Overload #1
}
template<typename A>
int a(A arg) {
return 2; // Overload #2
}
template<typename T>
struct S{};
int main() {
return a(S<int>());
}
通过模板类实例调用函数a
时,我希望编译器能选择更特殊的功能超载#1。根据编译器资源管理器的说法,Clang,GCC和Intel升至版本17实际上确实选择了Overload#1。相比之下,后来的英特尔编译器版本(18和19(选择Overload#2。
代码定义不明,还是最新的英特尔编译器版本错误?
以下未能在ICC 19.01上致电a()
:
template<template<typename, typename ...> class A, typename T, typename ... Ts>
int a(A<T, Ts...> arg){
return 1;
}
template<typename T>
struct S{};
int foo()
{
return a(S<int>());
}
根本无法将a()
视为候选人,这就是问题在问题中有所不同的原因。
C 17草稿说:
(其中p是模板 - 网板参数,a是实例化参数(
17.3.3 模板模板参数
- 模板 - 题词与模板模板参数p匹配,当p至少与 template-argumentA。如果P包含一个参数包,则A还匹配P,如果A的每个模板参数 匹配第
的模板头中的相应模板参数
到目前为止很好,<int
参数头与参数头 <T
匹配。
两个模板参数匹配 如果它们是相同的(类型,非类型,模板(,对于非类型模板 - 参数,则它们的类型是 等效(17.6.6.1(,和对于模板模板 - 参数,每个相应的模板参数 递归匹配。
看起来不错,int
和T
匹配。
当P的模板头包含模板参数包(17.6.3(时 参数包将匹配零或更多模板参数或模板参数包中的模板头组件包 与p中的模板参数包相同类型和形式的A(忽略这些模板是否 参数是模板参数包(。
这很难解析,但是对我来说似乎还可以。据我了解,编译器应该将参数与模板网板参数匹配。它明确地谈论了零或更多,我们在这里零。