Удалены ли конструкторы "доступными"?
Удаленный ответ на этот вопрос об удаленном конструкторе перемещения цитирует cppreference.com как говорится, что свойство is_move_constructible
должно быть успешным, если конструктор перемещения "доступен", даже если он не "полезен".
Стандарт фактически требует, чтобы перемещение-построение типа аргумента было корректным, поэтому ответ был не совсем прав.
Теперь стандарт неоднократно использует термин "доступный" в отношении конструкторов, ссылающихся на фактическую конструктивность. Например:
[C++11 8.5/6]:
Для инициализации объекта типа T
по умолчанию:
- Если
T
является классом класса (возможно, cv-qualit) (раздел 9), вызывается конструктор по умолчанию для T
(и инициализация плохо сформирована, если T
не имеет доступных значений по умолчанию конструктор); - if
T
- тип массива, каждый элемент инициализируется по умолчанию; - в противном случае инициализация не выполняется.
Если программа вызывает инициализацию по умолчанию объекта типа const-type T
, T
должен быть типом класса с предоставленным пользователем конструктором по умолчанию.
Тем не менее, я не могу найти нигде в стандарте, который категорически утверждает, что delete
d, явно определенный конструктор "доступен" или нет.
Другая [ненормативная] цитата, по-видимому, предполагает, что delete
d-ness и accessibility ортогональны:
[C++11: 12.2/1]:
[..] [Примечание: даже если нет вызова конструктора деструктора или копирования/перемещения, все семантические ограничения, такие как доступность (раздел 11) и функция удаляется (8.4.3), должны быть выполнены. [..]
- Я пропустил прохождение?
- Если нет, следует ли скорректировать страницу cppreference.com? Можете ли вы предложить лучшую формулировку?
- Должен ли стандарт быть более четким в этом отношении?
Ответы
Ответ 1
Из второй цитаты в вопросе я бы сказал, что на доступность не влияет delete
dness, и что первая цитата на самом деле вовсе не охватывает случай, когда такой конструктор может быть delete
d.
Этот сценарий вместо этого покрывается каким-то "общим требованием" в определении delete
:
[C++11: 8.4.3/2]:
Программа, которая ссылается на удаленную функцию неявно или явно, кроме объявления, плохо сформирована. [Примечание. Это включает вызов функции неявно или явно и формирование указателя или указателя на элемент функции. Он применяется даже для ссылок в выражениях, которые потенциально не оцениваются. Если функция перегружена, она ссылается только в том случае, если функция выбрана с помощью разрешения перегрузки. -end note]
Итак, cppreference.com, вероятно, мог бы сделать заметку о том, что существует еще один критерий, применимый к признаку is_move_constructible
, чем просто доступный конструктор перемещения. И здесь есть еще одна проблема: MoveConstructible
может быть удовлетворен CopyConstructible
тоже & dagger; поэтому даже конструктор перемещения сам по себе не является строго необходимым.
Все это вызывает еще один интересный момент: любая возможная реализация is_move_constructible
должна обязательно "ссылаться" на удаленный конструктор перемещения, что делает программу плохо сформированной, как указано в приведенной выше цитате. Тем не менее, я полагаю, что с помощью трюков SFINAE реализация может избежать фактического становления плохо сформированным.
& dagger; "Тип без перемещения ctor вообще, но с копией-ctor является конструктивным по конструкции (конструктивным из rvalue)". — DyP
Ответ 2
Я не хочу рассматривать то, что говорит веб-сайт cppreference, но, что касается стандарта, конструктивность не определяется с точки зрения "доступных конструкторов". Скорее, основным определением является определение is_constructible
, которое (С++ 11, 20.9.4.3/6):
is_constructible<T, Args...>
должно выполняться тогда и только тогда, когда следующее определение переменной будет хорошо сформировано для некоторой изобретенной переменной t
:
T t(create<Args>()...);
Проверка доступа выполняется как в контексте, не связанном с t
и любым из Args
. Учитывается только действительность непосредственного контекста инициализации переменных.
Таким образом, корректность гипотетического выражения на последней строке кода - это определяющий характер и скрытность, присущая чертам конструктивности. И это работает рука об руку с предложением, в котором говорится, что использование функции de & shy; leted приводит к плохо сформированной программе.