Ответ 1
Пример, не содержащий vector
, должен компилироваться. clang является правильным на этом.
Пример, включающий vector
, может компилироваться или не компилироваться, в зависимости от того, помечен ли поставщик std:: lib оператору присваивания перемещения vector
как noexcept
или нет. Стандарт не требует, чтобы эта подпись была noexcept
. Стандарт позволяет поставщикам добавлять noexcept
, если функция никогда не будет бросать.
libС++ помещает оператор присваивания vector
как noexcept
, если allocator_traits<allocator_type>::propagate_on_container_move_assignment::value
- true, а is_nothrow_move_assignable<allocator_type>::value
- true (как соответствие расширение). Оба они верны в реализации libС++ для std::allocator<T>
.
Обновление
Вытащить шляпу адвоката языка по запросу.
<disclaimer>
Я сощурился в половине стандарта, который не является моей областью знаний.
</disclaimer>
Не могли бы вы более подробно объяснить, почему должен компилироваться пример?
Все цитаты из последнего рабочего проекта С++ 1y, N3797.
Это указывает, что спецификация исключения разрешена для явно заданного специального члена:
8.4.2 Явно-дефолтные функции [dcl.fct.def.default]/p2
2 Явно-дефолтная функция может быть объявлена
constexpr
только если он был бы неявно объявлен какconstexpr
и может иметь явная спецификация исключений, только если она совместима (15.4) с спецификацией исключения для неявного объявления.
Это определяет "совместимые спецификации исключений:"
15.4 Спецификации исключений [except.spec]/p3
3 Две спецификации исключения совместимы, если:
оба не бросают (см. ниже), независимо от их формы,
оба имеют форму
noexcept
(константное выражение), а константные выражения эквивалентны, илиоба являются спецификациями динамического исключения, которые имеют одинаковый набор настроенных типов.
Bullet 2 охватывает ваш случай.
Это объясняет, почему неявно объявленный специальный член noexcept
в вашем примере:
15.4 Спецификации исключений [except.spec]/p14
14 Наследующий конструктор (12.9) и неявно объявленный специальный Функция члена (раздел 12) имеет спецификацию исключения. Если f наследующий конструктор или неявно объявленный дефолт конструктор, конструктор копирования, конструктор перемещения, деструктор, копия оператор присваивания или оператор переадресации, его неявный exception-specification указывает идентификатор типа
T
тогда и только тогда, когдаT
допускается исключительно спецификацией исключения функции вызывается с помощью неявного определенияf
;f
разрешает все исключения, если таковые имеются функция, которую он вызывает напрямую, разрешает все исключения, аf
имеет exception-specificationnoexcept(true)
, если каждая функция, которую он вызывает напрямую, не допускает исключений.
Поскольку каждая функция, вызванная неявным объявлением X& operator=(X&&)
, не допускает исключений (т.е. оператора присваивания перемещения F<true>
), этот специальный элемент noexcept(true)
.
Я считаю, что это гвоздь.