Удалены ли конструкторы "доступными"?

Удаленный ответ на этот вопрос об удаленном конструкторе перемещения цитирует 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 приводит к плохо сформированной программе.