Ответ 1
У меня нет N3936, но N3797 §5.12 [expr.cond]/3 содержит это (внимание мое):
В противном случае, если второй и третий операнды имеют разные типы и либо имеет (возможно, cv-qualified) тип класса, либо если оба являются значениями glvalues той же категории значений и того же типа, за исключением cv-qualification, делается попытка преобразовать каждый из этих операндов к типу другого. Процесс определения того, выражение операнда E1 типа T1 может быть преобразовано в соответствии с операндом выражение E2 типа T2 определяется следующим образом:
- Если E2 является lvalue: [удалено]
- Если E2 является значением x: [удалено]
- Если E2 является prvalue или если ни одно из преобразований выше, и по крайней мере один из операндов имеет (возможно, cv-qualit) Тип класса:
- если E1 и E2 имеют тип класса, а базовые типы классов одинаковы или - один из базовых классов другой:
E1 можно преобразовать в соответствие с E2, если класс T2 одинаковый тип как или базовый класс, класс T1 и cv-квалификация из T2 является той же самой cv-квалификацией, что и более высокая cv-квалификация чем, cv-квалификация T1. Если применяется преобразование, E1 является изменен на prvalue типа T2 с помощью copy-initializing временной введите T2 из E1 и используйте это временное значение как преобразованный операнд.Используя этот процесс, определяется, может ли второй операнд преобразованный в соответствие с третьим операндом, и будет ли третий операнд могут быть преобразованы в соответствии со вторым операндом. Если оба могут быть преобразованный, или можно преобразовать, но преобразование неоднозначно, программа плохо сформирована. Если ни один из них не может быть преобразован, операнды остаются без изменений, и дальнейшая проверка выполняется, как описано ниже. Если возможно одно преобразование, это преобразование применяется к выбранному операнду, а преобразованный операнд используется в место исходного операнда для остальной части этого раздела.
Теперь, чтобы скопировать инициализацию конечного операнда Base
из Derived()
, мы можем посмотреть в §13.3.1.3 [over.match.ctor]:
Когда объекты типа класса имеют прямую инициализацию (8.5) или копировать-инициализировать из выражения того же или производного класса тип (8.5), разрешение перегрузки выбирает конструктор. Для прямая инициализация, все функции кандидата конструкторы класса инициализируемого объекта. Для копирование-инициализация, все функции-кандидаты преобразуются конструкторы (12.3.1) этого класса. Список аргументов - это выражение-список или выражение-присваивание инициализатора.
Преобразование конструкторов определяется в §12.3.1 [class.conv.ctor] следующим образом:
Конструктор, объявленный без явного указателя функции указывает преобразование из типов его параметров в тип его классом. Такой конструктор называется конструктором преобразования.
Теперь, если вы поверите мне (ради того, чтобы не указывать больше, чем у меня 13.3), что prvalue Derived()
приведет к разрешению перегрузки, чтобы выбрать конструктор перемещения (принимая Base&&
), несмотря на удаление, это вызывает ошибку у Clang.
В заключение, Clang правилен при выдаче ошибки. Поскольку использование удаленной функции требует диагностики, это ошибка в GCC.