Перегрузка шаблонов функций различными шаблонами: компилятор Intel c ++ версии 18 дает результат, отличный от других компиляторов. Intel неверна? - PullRequest
10 голосов
/ 02 мая 2019

Рассмотрим следующий фрагмент кода:

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 фактически выбирают перегрузку # 1.Напротив, более поздние версии компилятора Intel (18 и 19) выбирают перегрузку № 2.

Неправильно ли определен код или более поздние версии компилятора Intel неверны?

1 Ответ

2 голосов
/ 02 мая 2019

Следующие не могут вызвать 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 черновик говорит:

(где P - параметр шаблона-шаблона, а A - аргумент создания экземпляра)

17.3.3 Аргументы шаблона шаблона

  1. Аргумент шаблона соответствует параметру шаблона шаблона P, когда P, по крайней мере, столь же специализирован, как аргумент шаблона A. Если P содержит пакет параметров, то A также соответствует P, если каждый из параметров шаблона A соответствует соответствующему параметру шаблона в заголовке шаблона P.

Пока все хорошо, <int заголовок аргумента соответствует заголовку параметра <T.

Два параметра шаблона соответствуют если они одного типа (тип, не тип, шаблон), то для нетипизированных параметров шаблона их типы эквивалент (17.6.6.1), и для шаблонов-параметров шаблона, каждый из соответствующих им шаблон-параметров совпадения, рекурсивно.

По-прежнему выглядит хорошо, int и T совпадают.

Когда шаблонная голова P содержит пакет параметров шаблона (17.6.3), шаблон Пакет параметров будет соответствовать нулю или более параметров шаблона или пакетов параметров шаблона в заголовке шаблона. A с тем же типом и формой, что и пакет параметров шаблона в P (игнорируя, являются ли эти шаблоны параметры являются пакетами параметров шаблона).

Это сложнее разобрать, но все же мне кажется, что все в порядке. Из того, что я понимаю, компилятор должен был сопоставить аргумент с параметром template-template. Это явно говорит о нуле или более, и у нас здесь ноль.

...