Подтвердить что ты не робот

Является ли конструктор копирования и назначение копии std:: runtime_error noexcept?

Все GCC 4.8.4, 4.9.3, 5.3.0 проходят тесты для std::exception (для любого из опций -std = С++ 11/1y/14/1z/17, если доступно):

static_assert(std::is_nothrow_copy_constructible<std::exception>::value, "test exception");
static_assert(std::is_nothrow_copy_assignable   <std::exception>::value, "test exception");

Хорошо, поскольку std::exception не имеет особых элементов (С++ 14 18.8.1):

namespace std {
  class exception {
  public:
    exception() noexcept;
    exception(const exception&) noexcept;
    exception& operator=(const exception&) noexcept;
    virtual ~exception();
    virtual const char* what() const noexcept;
  };
}

К сожалению, все вышеперечисленные компиляторы терпят неудачу при следующих static_assert s:

static_assert(std::is_nothrow_copy_constructible<std::runtime_error>::value, "test runtime_error");
static_assert(std::is_nothrow_copy_assignable   <std::runtime_error>::value, "test runtime_error");

Стандарт содержит только следующее о std::runtime_error в 19.2.6:

namespace std {
  class runtime_error : public exception {
  public:
    explicit runtime_error(const string& what_arg);
    explicit runtime_error(const char* what_arg);
  };
}

Но ничего не говорится об noexcept других (неявно объявленных специальных) членах и требованиях к реализации хранилища what_arg.

В стандарте (С++ 14) сказано следующее в 15.4/14:

Наследующий конструктор (12.9) и неявно объявленный специальный Функция члена (раздел 12) имеет спецификацию исключения. Если f наследующий конструктор или неявно объявленный дефолт конструктор, конструктор копирования, конструктор перемещения, деструктор, копия оператор присваивания или оператор переадресации, его неявный exception-specification указывает тип-идентификатор T тогда и только тогда, когда T разрешено спецификацией исключения функции, вызываемой напрямую по неявному определению fs; f разрешает все исключения, если какая-либо функция напрямую вызывает все исключения, а f имеет спецификация исключения noexcept (true), если каждая функция напрямую invokes не допускает исключений.

И следующее в 18.8.1/2:

Каждый стандартный класс библиотеки T, который проистекает из исключения класса, должен иметь общедоступный конструктор копий и публично доступный оператор назначения копирования, который не выходит с исключение.

Так как std::runtime_error не раскрывает реализацию хранилища what_arg, мы не знаем, являются ли это (специальные) члены неэксклюзивными или нет, поэтому невозможность создания конструктора копирования std::runtime_error или экземпляра копирования не разрешима. Наша единственная ставка - 18.8.1 выше.

Вопрос 1/a) Мы рассматриваем конструктор копирования std::runtime_error или присваивание копии как noexcept (1, 2). Это настоящая/современная/лучшая практика?

Вопрос 1/b) Нам не нужно явно указывать это в стандарте? (Как в 18.8.2, Class bad_exception)

Вопрос 1/c) Является ли это ошибкой в ​​GCC, что он не прошел тесты static_assert выше?

Вопрос 2) Если вышеуказанный вывод неверен, может ли кто-нибудь указать мне раздел (разделы) в стандарте, в котором указано, что std:: runtime_error имеет noexcept конструктор копирования (и назначение копии)? (Или там, где указано, что они не являются.)

4b9b3361

Ответ 1

Рассмотрим LWG 1371:

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

[Резолюция, предложенная голосованием:]

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

В собрании Batavia 2010 года было обнаружено, что [exception]/2 "this this":

Каждый стандартный класс библиотеки T, полученный из класса exception, должен иметь общедоступный конструктор копирования и общедоступный оператор назначения копирования, который не выходит с исключением.

Поэтому по-прежнему не предусмотрено, что эти специальные функции-члены noexcept. И в соответствии с тем, что спецификации неявных исключений определяются в [except.spec]/16, так как реализация может добавлять как произвольные параметры с аргументами по умолчанию и члены, специфичные для реализации, являются ли эти специальные функции-члены noexcept.