Wszystkie GCC 4.8.4, 4.9.3, 5.3.0 przejść testy dla std::exception
(dla każdego z -std = C++ 11/1r/14/1Z/17 warianty, gdzie jest dostępna):Czy konstruktor kopiowania i kopia przypisania std :: runtime_error noexcept?
static_assert(std::is_nothrow_copy_constructible<std::exception>::value, "test exception");
static_assert(std::is_nothrow_copy_assignable <std::exception>::value, "test exception");
Który jest w porządku, ponieważ std::exception
został noexcept specjalne członków (C++ 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; }; }
Niestety, wszystkie kompilatory powyżej nie na następujących 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");
Norma zawiera jedynie następujące informacje std::runtime_error
w 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); }; }
Ale nic nie mówi się o noexcept
Ness drugiej (niejawnie oświadczył specjalny) członków, ani realizacji pamięci wymagania what_arg
.
Standard (C++ 14) mówi o następujących 15,4/14:
konstruktora dziedziczenia (12.9) i pośrednio uznane szczególną funkcyjny element (punkt 12) mają wyjątku specyfikacją. Jeśli f jest dziedziczącym konstruktorem lub domyślnie domyślnym konstruktorem , kopiującym konstruktorem, konstruktorem ruchu, destruktorem, kopiującym operatorem przypisania lub przeniesionym operatorem przypisania, jego domyślna specyfikacja wyjątku określa identyfikator typu T, jeśli i tylko jeśli T jest dozwolone przez specyfikację wyjątków funkcji bezpośrednio wywoływanej przez niejawną definicję f; f zezwala na wszystkie wyjątki, jeśli jakakolwiek funkcja, którą to wywołuje, zezwala na wszystkie wyjątki, a f ma wyjątek-specyfikację wyjątku (true), jeśli każda funkcja wywoływana bezpośrednio przez użytkownika nie dopuszcza żadnych wyjątków.
A idąc 18.8.1/2:
Każde standardowe biblioteki klas T, która wywodzi się z klasy wyjątku powinien mają publicznie dostępny konstruktor kopiujący a publicznie dostępnego operatora przypisania kopiowaniem zrobienia nie wyjdzie z wyjątkiem .
Od std::runtime_error
nie wystawiać na realizację przechowywania what_arg
, nie wiemy, czy to (specjalne) członkowie są noexcept czy nie, więc noexceptness z std::runtime_error
„s kopia konstruktora lub skopiować członkowie przypisania są nierozstrzygalne. Nasz jedyny zakład to 18.8.1 powyżej.
Pytanie 1/a) Uważamy, że konstruktor kopiowania lub przypisanie kopii nie stanowią wyjątku (1, 2). Czy to prawda/state-of-the-art/najlepsza praktyka?
Pytanie 1/b) Czy nie musimy tego wyraźnie podawać w standardzie? (Jak w 18.8.2, klasa bad_exception
)
Pytanie 1/c) Czy jest to błąd w GCC, który nie spełnia powyższych testów static_assert?
Pytanie 2) Jeśli powyższe odliczenie jest błędne, czy ktoś mógłby wskazać mi sekcję (y) w standardzie, która stwierdza, że std :: runtime_error nie ma konstruktora kopiowania noexcept (i kopiowania przypisania)? (Lub gdzie stwierdza się, że nie są.)
Czy na pewno gcc 5.3.0 nie zalicza testów dla 'std :: runtime_error'? Wygląda na to, że [gcc 5.2.0 przechodzi testy] (http://melpon.org/wandbox/permlink/aHDNg8cs7ttnJlaW). – cpplearner
Próbowałem z g ++ - 5 (Ubuntu 5.3.0-3ubuntu1 ~ 14.04) 5.3.0 20151204 i nie udało się. –
Hmmmm, mogą wystąpić pewne problemy z moją instalacją GCC 5.3.0, ponieważ ma ona następujące znaczenie w /usr/include/c++/5.3.0/stdexcept: #if _GLIBCXX_USE_CXX11_ABI || _GLIBCXX_DEFINE_STDEXCEPT_COPY_OPS runtime_error (const runtime_error &) _GLIBCXX_ssss_USE_NOEXCEPT; runtime_error & operator = (const runtime_error &) _GLIBCXX_USE_NOEXCEPT; #endif ale nie wyemitowano błędu (zauważ, że zmodyfikowałem definicję _GLIBCXX_) –