c ++ 11 — Почему шаблон C ++, принимающий массив, не более специализирован, чем массив, принимающий указатель в соответствии с GCC 5.3 и Clang 4.0?

Почему следующие два объявления шаблона неоднозначны (поэтому ни один не является более специализированным, чем другой)? Я знаю, что этот вопрос много раз поднимался на Stack Overflow, но обычно люди отвечают, как решить двусмысленность, а не почему это произошло.

Я.
template <class T> void func(char* buf, T size) {}

II.
template <std::size_t N> void func(char (&buf)[N], std::size_t size) {}

Попытка пройти шаги стандарта C ++ 14 для разрешения частичного упорядочения шаблонов функций (14.5.6.2):

Создание преобразованного шаблона для каждого типа, не типового или шаблонного параметра шаблона (включая
пакеты параметров шаблона (их 14.5.3) синтезируют уникальный тип, значение или шаблон класса соответственно
и подставьте его для каждого вхождения этого параметра в тип функции шаблона.

Тип функции преобразованной функции I шаблона: void func(char*, U1), где U1 это какой-то уникальный синтетический тип.

Преобразованная функция Тип функции шаблона II: void func(char (&buf)[N1], std::size_t), где N1 это какая-то уникальная синтетическая ценность.

Используя тип функции преобразованного шаблона функции, выведите тип из другого шаблона.
как описано в 14.8.2.4.

Итак, давайте попробуем выполнить вывод типа с одной стороны (используя первый шаблон в качестве аргумента, а второй — как шаблон параметра) и с другой стороны.

Случай 1.

Шаблон параметров: template <std::size_t N> void func(char (&buf)[N], std::size_t size),
Преобразованный шаблон аргумента: void func(char*, U1),

Попытка вывести параметры шаблона. «char (&buf)[N]«не может быть выведено из»char*«тип. U1 не соответствует std::size_t введите либо. Не удалось.

Случай 2

Шаблон параметров: template <class T> void func(char* buf, T size),
Преобразованный шаблон аргумента: void func(char (&buf)[N1], std::size_t),

Попытка вывести параметры шаблона. Первый аргумент шаблона параметра не является типом вообще, и он совместим с char[], T должно быть выведено std::size_t,

Поэтому шаблон II должен быть более специализированным и должен быть выбран в следующем коде:

char buf[16];
func(buf, static_cast<std::size_t>(16));

Почему это не относится к GCC 5.3 и Clang 4.0?

15

Решение

Объявления шаблона не являются двусмысленными; следующий код компилируется и выполняется нормально:

#include <iostream>
#include <string>

using namespace std;

template<class T>
void func(char* buf, T size) {cout<<"void func(char*,T)\n";}
template<size_t N>
void func(char (&buf)[N], std::size_t size) {
cout<<"void func(char (&)[],size_t)\n";}

int main() {
char buf[3];
func(buf, 2);
func<3>(buf, 2);
func(reinterpret_cast<char (&)[3]>(buf), 2);
//next is ambiguous
//func(reinterpret_cast<char (&)[3]>(buf), size_t(2));
func<3>(reinterpret_cast<char (&)[3]>(buf), size_t(2));
return 0;
}

Однако закомментированный вызов неоднозначен. Для устранения неоднозначности используйте:

func<3>(reinterpret_cast<char (&)[3]>(buf), size_t(2));

Это работает нормально и вызывает правильную функцию.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]