Я считаю, что лязг здесь правильный.Разрешение перегрузки в C ++ работает в три этапа: сначала создается набор функций-кандидатов, который представляет собой набор всех функций, на которые потенциально может ссылаться вызов (в основном, набор всех функций, которые распознает разрешение имен).Этот начальный набор функций-кандидатов затем сужается, чтобы получить набор жизнеспособных функций (набор функций, которые могут принимать вызов с заданными аргументами).Наконец, жизнеспособные функции ранжируются для определения наилучшей жизнеспособной функции.Эта наилучшая жизнеспособная функция и будет называться в конечном итоге.
С [over.match.viable] / 4
В-третьих, для F
будетжизнеспособная функция, для каждого аргумента должна существовать неявная последовательность преобразования, которая преобразует этот аргумент в соответствующий параметр F
.[…]
На основе [over.best.ics] / 6 , в частности
Когда тип параметра не является ссылкой,Последовательность неявного преобразования моделирует инициализацию копирования параметра из выражения аргумента.[…]
может показаться, что такой неявной последовательности преобразования для void func(A a)
не существует из-за того, что необходимый конструктор помечен explicit
(при инициализации копирования произойдет сбой).Следовательно, функция не является жизнеспособной функцией и больше не рассматривается для разрешения перегрузки, в результате чего void func(const vector<int>& a)
остается единственным жизнеспособным кандидатом, то есть функцией, которая затем будет вызываться.
Кроме того, чисто наНа концептуальном уровне может показаться, что инициализация параметра copy-list-initialisation параметра может быть неверно сформирована только тогда, когда мы действительно знаем, какой параметр мы собираемся инициализировать, т. е. знаем, какая функция на самом деле будет вызываться.Если вызов набора перегрузки был бы недопустим в тот момент, когда есть единственный аргумент, который не является допустимым инициализатором для соответствующего параметра в каждой потенциальной функции-кандидате, тогда какой смысл перегрузки?Пока мы все еще работаем над выяснением, какую функцию вызывать, нет способа решить, будет ли инициализация неправильной или нет.Clang демонстрирует именно это поведение.Когда вы закомментируете перегрузку void func(const std::vector<int>& a)
, clang внезапно пожалуется, что вызов не сформирован…
попробуйте здесь