Являются ли удаленные конструкторы "доступными"?
Удаленный ответ на этот вопрос об удаленном конструкторе перемещения цитирует cppreference.com, говоря, что is_move_constructible
trait должен быть успешным, пока конструктор перемещения "доступен", даже если он не "применим".
Фактически стандарт требует, чтобы конструкция типа аргумента была правильно сформирована, поэтому ответ был не совсем правильным.
Теперь в стандарте неоднократно используется термин "доступный" по отношению к конструкторам, относящимся к фактической конструктивности. Например:
[C++11 8.5/6]:
По умолчанию инициализировать объект типаT
средства:
- если
T
является (возможно, cv-квалифицированным) типом класса (раздел 9), конструктором по умолчанию дляT
называется (и инициализация плохо сформирована, еслиT
не имеет доступного конструктора по умолчанию);- если
T
тип массива, каждый элемент инициализируется по умолчанию;- в противном случае инициализация не выполняется.
Если программа вызывает инициализацию по умолчанию для объекта типа с константой
T
,T
должен быть типом класса с предоставленным пользователем конструктором по умолчанию.
Тем не менее, я не могу найти нигде в стандарте, который категорически заявляет, delete
d, явно определенный конструктор "доступен" или нет.
Другая [ненормативная] цитата, кажется, предполагает, что delete
Д-ность и доступность ортогональны:
[C++11: 12.2/1]:
[..] [Примечание: даже если нет вызова деструктора или конструктора копирования / перемещения, все семантические ограничения, такие как доступность (пункт 11) и удаление функции (8.4.3), должны быть выполнены. [..]
- Я пропустил проход?
- Если нет, следует ли исправить страницу cppreference.com? Можете ли вы предложить лучшую формулировку?
- Должен ли стандарт быть яснее об этом в любом случае?
2 ответа
Из второй цитаты в вопросе я бы сказал, что доступность не зависит от delete
dness, и что первая кавычка на самом деле совсем не охватывает случай, когда такой конструктор может быть delete
д.
Этот сценарий вместо этого охватывается своего рода "всеобъемлющим" требованием в определении delete
:
[C++11: 8.4.3/2]:
Программа, которая ссылается на удаленную функцию неявно или явно, кроме как для ее объявления, является неправильно сформированной. [Примечание: это включает в себя вызов функции неявно или явно и формирование указателя или указателя на член функции. Это относится даже к ссылкам в выражениях, которые потенциально не оцениваются. Если функция перегружена, на нее ссылаются, только если функция выбрана разрешением перегрузки. —Конечная записка]
Таким образом, cppreference.com мог бы сделать заметку, что существует еще один критерий, который применяется к is_move_constructible
черта, чем просто, доступен ли конструктор перемещения. И здесь есть еще одна проблема, которая заключается в том, что MoveConstructible
может быть удовлетворен CopyConstructible
тоже †, поэтому даже сам конструктор перемещения не является строго необходимым.
Все это поднимает еще один интересный момент, однако, что любая возможная реализация is_move_constructible
обязательно должен "ссылаться" на удаленный конструктор перемещения, который делает программу некорректной, как указано в приведенной выше цитате. Тем не менее, я полагаю, что с помощью трюков SFINAE реализация может избежать неправильной работы.
† "Тип без ctor-хода вообще, но с ctor-копией является конструируемым с помощью Move (конструируемым из r-значения)". - dyp
Я не хочу говорить о том, что говорит веб-сайт cppreference, но что касается стандарта, конструктивность не определяется в терминах "доступных конструкторов". Скорее, основное определение is_constructible
(C++11, 20.9.4.3/6):
is_constructible<T, Args...>
должны быть выполнены тогда и только тогда, когда следующее определение переменной будет правильно сформировано для некоторой изобретенной переменной
t
:T t(create<Args>()...);
Проверка доступа выполняется как в контексте, не связанном с
T
и любой изArgs
, Учитывается только действительность непосредственного контекста инициализации переменной.
Таким образом, правильность гипотетического выражения в последней строке кода является определяющей характеристикой для черт конструктивности. И это работает рука об руку с предложением, в котором говорится, что использование удаленной функции приводит к неправильной программе.