【问题标题】:Function template overloading with variadic templates: Intel c++ compiler version 18 produces different result from other compilers. Is intel wrong?使用可变参数模板重载函数模板:英特尔 c++ 编译器版本 18 产生与其他编译器不同的结果。英特尔错了吗?
【发布时间】:2019-05-02 10:06:01
【问题描述】:

考虑以下代码sn-p:

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。根据compiler explorer,clang、gcc 和 intel 直到版本 17 实际上确实选择重载 #1。相比之下,后来的英特尔编译器版本(18 和 19)选择重载 #2。

是代码定义不正确还是最新的英特尔编译器版本有误?

【问题讨论】:

标签: c++ templates language-lawyer variadic-templates


【解决方案1】:

以下fails to call a() icc 19.01:

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模板模板参数

  1. 当 P 至少与 template-argument A. 如果 P 包含一个参数包,那么如果 A 的每个模板参数 A 也匹配 P 匹配P的template-head中对应的模板参数。

到目前为止一切顺利,&lt;int 参数头与参数头 &lt;T 匹配。

两个模板参数匹配 如果它们属于同一类型(类型、非类型、模板),对于非类型模板参数,它们的类型是 等效(17.6.6.1),和模板模板参数,每个对应的模板参数 递归匹配。

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

当 P 的模板头包含模板参数包(17.6.3)时,模板 参数包将匹配 零个或多个模板参数或模板头中的模板参数包 A 的类型和形式与 P 中的模板参数包相同(忽略那些模板是否 参数是模板参数包)。

这更难解析,但对我来说似乎没问题。据我了解,编译器应该已将参数与模板模板参数相匹配。它明确谈到零或更多,我们这里有零。

【讨论】:

  • 因此,最近的intel编译器似乎有一个错误,上面的代码是有效的。你同意吗,@MichaelVeksler?
  • @user2296653 是的,这看起来像是最近的英特尔编译器中的一个错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-26
  • 1970-01-01
  • 2021-08-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多