使用可变参数模板重载函数模板:英特尔 C++ 编译器版本 18 产生与其他编译器不同的结果。英特尔错了吗?
Function template overloading with variadic templates: Intel c++ compiler version 18 produces different result from other compilers. Is intel wrong?
考虑以下代码片段:
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>());
}
在使用模板 class 的实例调用函数 a
时,我希望编译器 select 更特殊的函数重载 #1。根据 compiler explorer,17 版之前的 clang、gcc 和 intel 实际上会 select 重载 #1。相比之下,后来的英特尔编译器版本(18 和 19)select 重载 #2.
是代码定义错误还是最近的英特尔编译器版本有误?
icc 19.01 上的以下 fails to call 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 draft 说:
(其中 P 是模板模板参数,A 是实例化参数)
17.3.3 Template template arguments
- A template-argument matches a template template-parameter P when P is at least as specialized as the
template-argument A. If P contains a parameter pack, then A also matches P if each of A’s template parameters
matches the corresponding template parameter in the template-head of P.
到目前为止一切顺利,<int
参数头匹配参数头 <T
。
Two template parameters match
if they are of the same kind (type, non-type, template), for non-type template-parameters, their types are
equivalent (17.6.6.1), and for template template-parameters, each of their corresponding template-parameters
matches, recursively.
看起来还是不错,int
和 T
匹配。
When P’s template-head contains a template parameter pack (17.6.3), the template
parameter pack will match zero or more template parameters or template parameter packs in the template-head
of A with the same type and form as the template parameter pack in P (ignoring whether those template
parameters are template parameter packs).
这更难解析,但对我来说似乎没问题。据我了解,编译器应该将参数与模板模板参数相匹配。它明确地谈论零或更多,我们这里有零。
考虑以下代码片段:
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>());
}
在使用模板 class 的实例调用函数 a
时,我希望编译器 select 更特殊的函数重载 #1。根据 compiler explorer,17 版之前的 clang、gcc 和 intel 实际上会 select 重载 #1。相比之下,后来的英特尔编译器版本(18 和 19)select 重载 #2.
是代码定义错误还是最近的英特尔编译器版本有误?
icc 19.01 上的以下 fails to call 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 draft 说:
(其中 P 是模板模板参数,A 是实例化参数)
17.3.3 Template template arguments
- A template-argument matches a template template-parameter P when P is at least as specialized as the template-argument A. If P contains a parameter pack, then A also matches P if each of A’s template parameters matches the corresponding template parameter in the template-head of P.
到目前为止一切顺利,<int
参数头匹配参数头 <T
。
Two template parameters match if they are of the same kind (type, non-type, template), for non-type template-parameters, their types are equivalent (17.6.6.1), and for template template-parameters, each of their corresponding template-parameters matches, recursively.
看起来还是不错,int
和 T
匹配。
When P’s template-head contains a template parameter pack (17.6.3), the template parameter pack will match zero or more template parameters or template parameter packs in the template-head of A with the same type and form as the template parameter pack in P (ignoring whether those template parameters are template parameter packs).
这更难解析,但对我来说似乎没问题。据我了解,编译器应该将参数与模板模板参数相匹配。它明确地谈论零或更多,我们这里有零。