Я собираюсь сделать небольшую переписку неверной версии, чтобы помочь поговорить о том, что происходит.
struct T {
enum { int_t,float_t } m_type;
template <
typename Integer,
typename U = std::enable_if_t<std::is_integral<Integer>::value>
>
T(Integer) : m_type(int_t) {}
template <
typename Floating,
typename U = std::enable_if_t<std::is_floating_point<Floating>::value>
>
T(Floating) : m_type(float_t) {} // error: cannot overload
};
Все, что я сделал, - присвоил ранее анонимному второму параметру имя - U
.
Причина, по которой эта первая версия не работает, заключается в том, что нет способа выбрать между ними в случае, если вы явно задаете второй параметр.Например 1
f<int,void>(1);
На какую функцию это следует выводить?Если это целочисленная версия, она, конечно, работает, но как насчет плавающей версии.Ну, у него есть T = int
, но как насчет U
?Ну, мы только что дали ему тип bool
, поэтому у нас есть U = bool
.Таким образом, нет никакого способа выбрать между двумя в этом случае, они идентичны.(Обратите внимание, что в целочисленной версии у нас все еще есть U = bool
).
Так что, если мы явно дадим имя второму параметру шаблона, вычет будет неудачным.И что?В реальном случае это не должно происходить.Мы собираемся использовать что-то вроде
f(1.f);
, где возможно сделать вычет.Хорошо, вы заметите, что компилятор выдает ошибку даже без объявления .Это означает, что он решил, что он не может сделать вывод, даже не дав ему тип вывода, поскольку обнаружил проблему, на которую я указал выше.Ну а из intro.defs мы имеем сигнатуру
«шаблон функции-члена класса» имя, список параметров-типов, класс, членом которого является функция, cv-квалификаторы (если есть), ref-квалификатор (если есть), тип возвращаемого значения (если есть) и список параметров шаблона
И из temp.over.link мы знаем, чтодва определения функций шаблона не могут иметь одну и ту же сигнатуру.
К сожалению, стандарт кажется довольно расплывчатым в том, что именно означает «список параметров шаблона».Я искал пару разных версий стандарта, и ни одна из них не дала четкого определения, которое я смог найти.Не ясно, является ли «список параметров шаблона» тем же, если параметр типа с другим значением по умолчанию является уникальным или нет.Учитывая, что я собираюсь сказать, что это на самом деле неопределенное поведение, и ошибка компилятора является приемлемым способом справиться с этим.
Вердикт еще не вынесен, если кто-то может найти явное определение в стандартедля "списка параметров шаблона" я был бы рад добавить его для более удовлетворительного ответа.
Редактировать:
Как отметил xskxkr, самый обновленный черновик на самом деле дает более конкретныйопределение.Шаблоны имеют template-head , который содержит template-parameter-list , который является серией template-parameters .Он не включает аргументы по умолчанию в определении.Таким образом, в соответствии с текущим проектом, иметь два одинаковых шаблона, но с разными аргументами по умолчанию, однозначно неправильно, но вы можете «обмануть» его, думая, что у вас есть две отдельные головки-шаблона , сделавтип второго параметра зависит от результата enable_if
.
1 В качестве примечания, я не смог найти способ явно создать экземпляр шаблонаконструктор не шаблонного класса.Это странная конструкция.Я использовал f
в своих примерах, так как я мог заставить его работать с бесплатной функцией.Может быть, кто-то еще может понять синтаксис?