2016-01-27 14 views
10

GCC 4.8.4、4.9.3、5.3.0のすべてが(-std = C++ 11/1Y/14/1Z/17の任意の利用可能なオプションのために)std::exceptionためのテストに合格: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; 
    }; 
} 

残念ながら、上記のコンパイラのすべては、以下のstatic_assert秒で失敗:std::exceptionはnoexcept特別会員(C++ 14 18.8.1)がいるので、大丈夫です

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

標準のみ19.2.6約std::runtime_error次のものが含まれます。

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の要件。

標準(C++ 14)15.4/14で次の言葉:

継承コンストラクタ(12.9)と暗黙的に宣言された特別な メンバ関数(条項12)は例外仕様を有しています。 fが 継承コンストラクタまたは暗黙的に宣言されたデフォルトの コンストラクタ、コピーコンストラクタ、移動コンストラクタ、デストラクタ、コピー 代入演算子、または代入演算子を移動する場合、その暗黙的な 例外指定では、T fの暗黙の定義によって が直接呼び出された関数の例外仕様によって許可された です。 fが直接呼び出す関数がすべての例外を許可する場合はすべての例外を許可し、直接呼び出すすべての関数が例外を許可しない場合はfは 例外仕様noexcept(true)を持ちます。

そして18.8.1/2で次

クラス例外から派生した各標準ライブラリのクラスT は、公的にアクセス可能なコピーコンストラクタと行う公的 アクセスコピー代入演算子を持たなければなりません 例外で終了しないでください。

std::runtime_errorwhat_argストレージの実装を公開していませんので、我々はそれが(特別な)メンバーがnoexceptかないので、std::runtime_error年代のnoexceptnessはコピーコンストラクタや代入メンバーが決定不能ですコピーだかどうかわかりません。私たちの唯一の賭けは18.8.1です。

質問1/a)std::runtime_errorのコピーコンストラクタまたはコピー割り当てをnoexcept(1,)と見なします。これは本当の/最先端の/ベストプラクティスですか?

質問1/b)標準でこれを明示する必要はありませんか? (18.8のように。2、Class bad_exception

質問1/c)上記のstatic_assertテストに失敗したGCCのバグですか?

質問2)上記の控除が間違っていると、std :: runtime_errorにnoexceptコピーコンストラクタ(およびコピー代入)があることを示す標準のセクションに誰かを指摘できますか? (それとも、そうでないと述べている。)

+0

gcc 5.3.0は 'std :: runtime_error'のテストに合格していますか? [gcc 5.2.0がテストに合格したようです](http://melpon.org/wandbox/permlink/aHDNg8cs7ttnJlaW)。 – cpplearner

+0

g ++ - 5(Ubuntu 5.3.0-3ubuntu1〜14.04)5.3.0 20151204で試してみましたが、失敗します。 –

+0

GCC 5.3.0のインストールには、/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 しかし、エラーは出ませんでした。(私は_GLIBCXX_defineを変更しました) –

答えて

2

LWG 1371を考えてみましょう:

節19に定義された例外タイプのいずれもコピーで例外を投げるかの操作を移動することができませんが、明確な存在していません

その操作がそれを証明するための例外仕様を持っているという仕様。暗黙的に宣言されたコンストラクタは、すべてのデータメンバーが同様にnoexcept操作を宣言している場合、基本クラス(最終的にはstd::exception)から例外仕様を受け取り、暗黙的にnoexcept例外仕様を生成します。表現が明示されていないので、明示的に実装上の制約として明記しない限り、非投棄操作は想定できません。

[投票コメントによって提案された解像度:]

は、グローバル保証が追加に依存している節19 で定義されているすべての例外タイプは、暗黙的に操作がそれらの操作上の非投げ 例外仕様を持って宣言しました。 2010バタビア会議で

、それは[exception]/2は「これをカバー」ことが判明した。

クラスexceptionから派生した各標準ライブラリのクラスTは、公的にアクセス可能なコピーコンストラクタと公的にアクセス可能なコピーを持たなければなりません例外を伴って終了しない代入演算子。

したがって、これらの特別なメンバー関数がnoexceptであることは依然として必須ではありません。そして暗黙の例外仕様が[except.spec]/16で決定される方法によれば、実装はデフォルトの引数とメンバを持つ任意のパラメータを両方追加できるため、これらの特別なメンバ関数がnoexceptであるかどうかにかかわらず実装固有です。


関連する問題