Должна ли инициализация аргумента deduction guide учитываться при дедукции специализации шаблона класса?

как продолжение этого вопрос, Я проверил поведение как clang, так и gcc. Похоже, что два компилятора имеют различную интерпретацию стандарта c++.

в приведенном ниже примере GCC отказывается компилировать, если не копируемый аргумент необходимо скопировать в соответствии с аргументом гипотетического конструктора руководства по дедукции. Clang не выполняет эту проверку:

#include <cstddef>

struct not_copyable{
    not_copyable()=default;
    not_copyable(const not_copyable&)=delete;
};
struct movable{
    movable()=default;
    movable(movable&&);
};

template <typename T, size_t N>
struct A
 { template <typename ... Ts> A (Ts const & ...) {} };

template <typename T, size_t N>
struct B
 { template <typename ... Ts> B (const Ts & ...) {} };

template <typename T, typename ... Ts>
A(T const &, Ts const & ...) -> A<T, 1U + sizeof...(Ts)>;

template <typename T, typename ... Ts>
B(T, Ts ...) -> B<T, 1 + sizeof...(Ts)>;


int main()
 {
   not_copyable nc;
   movable m;

   auto a0 = A{nc};    // gcc & clang -> compile
   auto a1 = A{m};     // gcc & clang -> compile
   auto b0 = B{nc};    // clang ->compile;  gcc -> error
   auto b1 = B{m};     // clang ->compile;  gcc -> error
 }

в think правильное поведение определено в этом абзаце стандарт C++[окончен.спичка.класс.вычесть]/2:

Инициализация и разрешение перегрузки выполняются, как описано в [dcl.init] и [конец.спичка.ктор], [прием.спичка.копировать или [над.спичка.list] (в зависимости от типа инициализации исполнении) для объекта гипотетического типа класса, где выбранные функции и шаблоны функций считаются конструкторы этого типа класса С целью формирования перегрузка set,[...]

Я подчеркнул "С целью формирования набора перегрузки" потому что я думаю, что это где лязг и gcc расходятся. Clang, похоже, не проверяет, является ли гипотетический конструктор руководства по дедукции жизнеспособная функция, но gcc делает. Какой компилятор прав?

1 ответов


Clang, похоже, не проверяет, является ли гипотетический конструктор руководства по дедукции жизнеспособной функцией, но gcc делает это.

на самом деле, руководство дедукции и жизнеспособной функции. Функция жизнеспособна просто означает, что количество аргументов совпадает, ограничения удовлетворены, и вы можете сформировать неявные последовательности преобразования для каждой пары параметров/аргументов. И когда мы проверяем, существует ли ICS, [окончен.лучший.ics] / 2:

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

очень важно, что удаление функции не делает ее нежизнеспособной, потому что важно, чтобы она все еще могла стать лучшим жизнеспособным кандидатом. Это означает, что тот факт, что not_copyableс копией конструктор удаляется должен вступать в силу только тогда, когда мы фактически вызываем его.

например, как gcc, так и clang отклоняют эту программу. #1 это жизнеспособных кандидат, и это лучший жизнеспособный кандидат, несмотря на конструктор удаленной копии:

struct NC {
    NC() = default;
    NC(NC const&) = delete;
    NC& operator=(NC const&) = delete;
};       

void foo(NC );                            // #1
template <typename T> void foo(T const&); // #2

int main() {
    NC nc;
    foo(nc);
}

но мы никогда на самом деле вызов синтезированные функции и шаблоны функций, которые мы используем для дедукции. Мы просто выполняем разрешение перегрузки и выбираем лучшее кандидат-который мы используем только для выбора типа класса, а затем начинаем все сначала. Мы ни в коем случае не должны требовать копирования.

Я думаю, что это ошибка gcc. Подал 86439.