使用可变参数模板的功能模板重载:英特尔c ++编译器版本18产生的结果与其他编译器不同。英特尔错了吗?

use*_*653 10 c++ templates language-lawyer variadic-templates

考虑以下代码片段:

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>());
}
Run Code Online (Sandbox Code Playgroud)

a使用模板类的实例调用函数时,我希望编译器选择更特殊的函数重载#1。根据编译器资源管理器的说法,直到版本17的clang,gcc和intel确实选择了#1重载。相反,后来的intel编译器版本(18和19)选择#2重载。

代码定义不正确吗?还是最新的intel编译器版本错误?

Mic*_*ler 2

以下内容无法在 icc 19.01 上调用:a()

\n\n
template<template<typename, typename ...> class A, typename T, typename ... Ts>\nint a(A<T, Ts...> arg){\n    return 1;\n}\n\ntemplate<typename T>\nstruct S{};\n\nint foo()\n{\n    return a(S<int>());\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

它根本无法将其视为a()候选者,这就是问题中的重载不同的原因。

\n\n

C++17 草案说:

\n\n

(其中 P 是模板-模板参数,A 是实例化参数)

\n\n
\n

17.3.3模板模板参数

\n\n
    \n
  1. 当 P 至少与模板参数 A 一样专用时,模板参数与模板参数 P 匹配。如果 P 包含参数包,则 A 也与 P 匹配,前提是每个 A\xe2\x80\x99s 模板parameters\n 匹配 P 的 template-head 中对应的模板参数。
  2. \n
\n
\n\n

到目前为止一切顺利,<int参数 head 与参数 head 匹配<T

\n\n
\n

如果两个模板参数属于同一类型(类型、非类型、模板),则它们匹配\n;对于非类型模板参数,它们的类型\n 是等效的 (17.6.6.1);对于模板模板参数,\n它们各自对应的模板参数\n 递归地匹配。

\n
\n\n

看起来还是不错的,intT很搭配。

\n\n
\n

当 P\xe2\x80\x99s template-head 包含模板参数包 (17.6.3) 时,模板参数包将与 A 的 template-head\n 中的零个或多个模板参数或模板参数包匹配与P中模板参数包的类型和形式相同(忽略这些模板参数是否是模板参数包)。

\n
\n\n

这更难解析,但对我来说似乎还可以。据我了解,编译器应该将参数与模板模板参数相匹配。它明确地谈论零或更多,而我们这里有零。

\n