考虑以下代码片段:

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,直到版本17的clang,gcc和intel确实选择了#1重载。相反,后来的intel编译器版本(18和19)选择重载#2。

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

最佳答案

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是template-template参数,而A是实例化参数)



到目前为止,<int参数head与参数head <T相匹配。



看起来仍然不错,intT匹配。



这很难解析,但是对我来说似乎还可以。据我了解,编译器应该已经将参数与template-template参数进行了匹配。它明确地谈论零或更多,这里我们零。

07-24 09:45
查看更多