Эквивалентны ли эти три конструктора по умолчанию в C++?

Рассмотрим следующий код:

#include <type_traits>

template<typename T>
struct A1 {
    T t;

    // implicitly-declared default constructor
};

template<typename T>
struct A2 {
    T t;

    // explicitly-declared default constructor without noexcept
    A2() = default;
};

template<typename T>
struct A3 {
    T t;

    // explicitly-declared default constructor with noexcept
    A3() noexcept(std::is_nothrow_default_constructible<T>::value) = default;
};

Эквивалентны ли эти три конструктора по умолчанию в C++?

Первые два эквивалентны описанию здесь. Спецификация третьего исключения зависит от того, имеет ли выражение значение true или нет.

user12002570 28.02.2024 09:20
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
167
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Эквивалентны ли эти три конструктора по умолчанию в C++?

Да, векторы по умолчанию эквивалентны в контексте noexcept specification.

Это можно увидеть из default ctor:

Неявно объявленный (или заданный по умолчанию при первом объявлении) конструктор по умолчанию имеет спецификацию исключения, как описано в спецификации динамического исключения (до C++17) и спецификации noException (начиная с C++17).

Итак, мы переходим к спецификации noException:

Каждая функция в C++ либо не выбрасывает, либо потенциально выбрасывает:

  • потенциально выбрасывающие функции:
    • функции, объявленные без спецификатора noException, за исключением
      • конструкторы по умолчанию, конструкторы копирования, конструкторы перемещения, которые объявлены неявно или по умолчанию при первом объявлении, если только
        • конструктор для базы или члена, который будет вызывать неявное определение конструктора, потенциально выбрасывает (см. ниже)

Я думаю, независимо от того, является ли std::is_nothrow_default_constructible<T>::valuetrue или false, эти три вектора по умолчанию кажутся эквивалентными.

xmllmx 28.02.2024 09:33

@xmllmx Источник?

user12002570 28.02.2024 09:34

Просто моя интуиция: если ctor по умолчанию T потенциально выбрасывает, то A1() & A2() тоже потенциально выбрасывает; в противном случае, если ctor по умолчанию не генерирует генерацию, то T и A1() также должны быть негенерирующими. Итак, я думаю, что эти три должны быть эквивалентны.

xmllmx 28.02.2024 09:36

@user12002570 user12002570, вы не заключили в кавычки текст после <<unless>>: «конструктор для базы или члена, который будет вызывать неявное определение конструктора, потенциально выбрасывает (см. ниже)». Итак, я бы сказал, что все три конструктора имеют одну и ту же подпись (С++ 17 и более поздние версии)?

pptaszni 28.02.2024 09:38

@xmllmx Другими словами, noexcept(std::is_nothrow_default_constructible<T>::value) не имеет права голоса при принятии решения о том, бросается ли это или нет? Я также вижу фразу «специальные функции-члены по умолчанию» в последней цитируемой ссылке в моем ответе. Таким образом, эти три кажутся эквивалентными.

user12002570 28.02.2024 09:39

@user12002570 user12002570, я думаю, если ctor по умолчанию T потенциально выдает ошибку, то std::is_nothrow_default_constructible<T>::value должно быть false; иначе true.

xmllmx 28.02.2024 09:40

«Я думаю, что если ctor по умолчанию T потенциально выбрасывает, то std::is_nothrow_default_constructible<T>::value должно быть ложным; в противном случае — true». Это ложь.

Jeff Garrett 28.02.2024 16:16

«Просто моя интуиция: если ctor по умолчанию T потенциально выбрасывает, то A1() и A2() также должны быть потенциально выбрасывающими; в противном случае, если ctor по умолчанию T не выбрасывает, тогда A1() и A2() также должны быть невыбрасывающими. - бросание». У A1 нет конструктора, являющегося агрегатом. И, как уже упоминалось, «потенциально выбрасываемый по умолчанию ctor T» — это не (только) то, что тестирует признак типа.

Jeff Garrett 28.02.2024 16:18

Два и три эквивалентны; три просто подвержены ошибкам и избыточны.

Первый эквивалентен с точки зрения функциональности конструктора. Однако, поскольку у нее нет явно объявленного (даже заданного по умолчанию) конструктора, структура является агрегатом, в отличие от двух других.

Вопрос в noexcept specification. Я не понимаю, как это авторитетно отвечает на вопрос.

Alan 28.02.2024 09:26

@Алан Вы имеете в виду, что ожидаете цитат из стандарта, подтверждающих мое утверждение?

Sebastian Redl 28.02.2024 09:38

Вопрос в том, эквивалентны ли они не только в noException?

Jeff Garrett 28.02.2024 14:43

@JeffGarrett Насколько я понимаю, вопрос заключается в том, эквивалентны ли ctors в контексте спецификации noException, а не в том, является ли он агрегатным или нет, или как инициализировать объект этого типа и т. д.

user12002570 28.02.2024 16:31

Справедливо. Наверное, я прочитал это по-другому. Я вижу «эквивалентны ли эти конструкторы» (в заголовке и выделено жирным шрифтом в теле), и нет никаких вопросов о том, эквивалентны ли они относительно noException или любого другого конкретного фактора.

Jeff Garrett 28.02.2024 16:47

@user12002570 user12002570 Я не читал это таким образом, но тот факт, что ваш ответ принят, предполагает, что вы лучше угадаете намерения ОП.

Sebastian Redl 28.02.2024 20:40
Ответ принят как подходящий

Ничто из этого не эквивалентно друг другу.

Во-первых, A1<T> является совокупностью , тогда как A2<T> и A3<T> таковыми не являются. См. богболт. Определение агрегата различается в разных стандартах, и это агрегат (опять же) в C++20... поэтому, если вы поддерживаете старые стандарты, A1<T> будет иметь очень разные возможности в каждом из них.

Это оказывает сильное влияние на то, где и как они могут быть построены. Если можно построить T, можно построить A1<T>, но не обязательно A2<T> или A3<T>. См. богболт .

Итак, A1<T> отличается от других тем, сможете ли вы вообще его построить.

A2<T> и A3<T> различаются тем, является ли конструктор по умолчанию noexcept. std::is_nothrow_default_constructible_v не проверяет, является ли значение не только конструируемым, но и разрушаемым. В то время как объявление по умолчанию без спецификации noException проверяет только конструкторы. См. богболт . (Это LWG 2116.)

Другие вопросы по теме