2016-01-27 10 views
10

Alle GCC 4.8.4, 4.9.3, 5.3.0 passieren die Tests für std::exception (für jeden von -std = C++ 11/1J/14/1Z/17-Optionen, wo verfügbar):Sind der Kopierkonstruktor und die Kopierzuordnung von 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"); 

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

Leider alle oben nicht auf den folgenden static_assert s Compiler:

was in Ordnung ist, da std::exception hat spezielle Mitglieder (C++ 14 18.8.1) noexcept

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"); 

Die Norm enthält nur die folgenden über std::runtime_error in 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); 
    }; 
} 

Aber nichts gesagt über die noexcept ness des anderen (implizit besondere deklariert) Mitglieder noch die Speicherimplementierung Anforderungen von what_arg.

der Standard (14 C++) sagt der folgende in 15.4/14:

Ein Vererbungs Konstruktor (12.9) und ein implizit deklarierte spezielle Mitgliedsfunktion (Ziffer 12), eine Ausnahme-Spezifikation. Wenn f ein ererbender Konstruktor oder ein implizit deklarierter Standardwert Konstruktor ist, Konstruktor kopieren, Konstruktor verschieben, Destruktor, Kopie Zuweisungsoperator oder Zuweisungsoperator verschieben, gibt seine implizite Ausnahmespezifikation die Typ-ID T genau dann an, wenn T ist erlaubt durch die Ausnahmespezifikation einer direkt aufgerufenen Funktion durch die implizite Definition von f; f erlaubt alle Exceptions, wenn eine Funktion es direkt aufruft erlaubt alle Exceptions, und f hat die Exception-Spezifikation noexcept (true), wenn jede Funktion, die es direkt aufruft, keine Ausnahmen erlaubt.

und die folgend in 18.8.1/2:

Jede Standard-Bibliothek Klasse T, die von Klassen Ausnahme leitet soll haben eine öffentlich zugängliche Copykonstruktor und einen öffentlich zugänglichen Kopierzuweisungsoperator, tun nicht mit einer Ausnahme beenden.

Da std::runtime_error aussetzt nicht die Umsetzung der what_arg Lagerung, wissen wir nicht, ob es (spezielle) Mitglieder sind noexcept oder nicht, so dass die noexceptness von std::runtime_error ‚s Copy-Konstruktor oder kopieren Zuordnung Mitglieder unentscheidbar sind. Unsere einzige Wette ist 18.8.1 oben.

Frage 1/a) Wir betrachten std::runtime_error Copy Constructor oder kopieren Zuordnung zu noexcept (1, 2). Ist das wahr/State-of-the-Art/Best Practice?

Frage 1/b) Müssen wir dies nicht explizit in der Norm angeben? (Wie in 18.8.2, Klasse bad_exception)

Frage 1/c) Ist es ein Fehler in GCC, dass es die oben genannten static_sert-Tests nicht besteht?

Frage 2) Wenn der obige Abzug falsch ist, könnte mich jemand auf die Sektion (en) im Standard verweisen, die besagt, dass std :: runtime_error keinen execept Kopierkonstruktor (und Kopierzuweisung) hat? (Oder, wo es heißt, dass sie nicht sind.)

+0

Sind Sie sicher, dass gcc 5.3.0 die Tests für 'std :: runtime_error' nicht besteht? Es scheint, dass [gcc 5.2.0 die Tests besteht] (http://melpon.org/wandbox/permlink/aHDNg8cs7ttnJlaW). – cpplearner

+0

Ich versuchte mit g ++ - 5 (Ubuntu 5.3.0-3ubuntu1 ~ 14.04) 5.3.0 20151204 und es schlägt fehl. –

+0

Hmmmm, es könnte einige Probleme mit meiner GCC 5.3.0-Installation geben, da sie folgendes in /usr/include/c++/5.3.0/stdexcept enthält: #if _GLIBCXX_USE_CXX11_ABI || _GLIBCXX_DEFINE_STDEXCEPT_COPY_OPS runtime_error (const runtime_error &) _GLIBCXX_ssss_USE_NEXCEPT; runtime_error & operator = (const runtime_error &) _GLIBCXX_USE_NOEXCEPT; #endif aber es gab keinen Fehler (beachten Sie, dass ich die Definition _GLIBCXX_ geändert habe) –

Antwort

2

Betrachten LWG 1371:

Keine der Ausnahmetypen definiert in Klausel 19 erlaubt eine Ausnahme auf Kopie zu werfen oder Operationen verschieben, aber es gibt keine klare Spezifikation, dass die Operationen eine Ausnahmebeschreibung haben, um dies zu beweisen. Beachten Sie, dass die implizit deklarierten Konstruktoren, die die Ausnahmespezifikation von ihrer Basisklasse (ultimativ std::exception) übernehmen, implizit eine noexcept Ausnahmespezifikation generieren, wenn alle ihre Datenelemente gleichermaßen noexcept Operationen deklarieren. Da die Repräsentation nicht spezifiziert ist, können wir keine nicht auflösenden Operationen annehmen, es sei denn, dies wird ausdrücklich als Einschränkung für die Implementierung angegeben.

[Resolution durch den Stimmzettel Kommentar vorgeschlagen:]

eine globale Garantie hinzufügen, dass alle definierten Ausnahmetypen in Klausel 19 , die auf implizit deklariert verlassen sich Operationen an diesen Operationen eine nicht werfen Ausnahmespezifikation haben.

In 2010 Batavia Sitzung wurde festgestellt, dass [exception]/2 „diese bedeckt“:

Jede Standard-Bibliothek Klasse T, die von Klasse abgeleitet exception wird eine öffentlich zugängliche Copykonstruktor hat und eine öffentlich zugängliche Kopie Zuweisungsoperator, der nicht mit einer Ausnahme beendet wird.

Daher ist es immer noch nicht vorgeschrieben, dass diese speziellen Elementfunktionen noexcept sind. Und je nachdem, wie implizite Ausnahmespezifikationen in [except.spec]/16 bestimmt werden, da eine Implementierung beide beliebigen Parameter mit Standardargumenten und -elementen hinzufügen kann, ist es implementierungsspezifisch, ob diese speziellen Elementfunktionen noexcept sind oder nicht.


Verwandte Themen