名前空間
変種
操作

動的例外指定

提供: cppreference.com
< cpp‎ | language
 
 
C++言語
一般的なトピック
フロー制御
条件付き実行文
繰り返し文 (ループ)
ジャンプ文
関数
関数宣言
ラムダ関数宣言
inline 指定子
例外指定 (C++20未満)
noexcept 指定子 (C++11)
例外
名前空間
指定子
decltype (C++11)
auto (C++11)
alignas (C++11)
記憶域期間指定子
初期化
代替表現
リテラル
ブーリアン - 整数 - 浮動小数点
文字 - 文字列 - nullptr (C++11)
ユーザ定義 (C++11)
ユーティリティ
属性 (C++11)
typedef 宣言
型エイリアス宣言 (C++11)
キャスト
暗黙の変換 - 明示的な変換
static_cast - dynamic_cast
const_cast - reinterpret_cast
メモリ確保
クラス
クラス固有の関数特性
特別なメンバ関数
テンプレート
その他
 
 

関数が直接または間接的に投げる可能性のある例外の一覧を指定します。

目次

[編集] 構文

throw( ) (1) (C++11で非推奨)(C++20で削除)
throw(typeid, typeid, ...) (2) (C++11で非推奨)(C++17で削除)
1) 例外を投げない動的例外指定。
(C++17未満)
1) noexcept(true) と同じです。
(C++17以上)
2) 明示的な動的例外指定。

この指定はラムダ宣言子に対して、または型が関数型、関数へのポインタ型、関数への参照型、メンバ関数へのポインタ型である関数、変数、または非静的データメンバのトップレベルの (C++17未満)宣言子である関数宣言に対してのみ使用できます。 引数の宣言子または戻り値の型の宣言子に対しても使用できます。

void f() throw(int); // OK、関数の宣言。
void (*pf)() throw (int); // OK、関数へのポインタの宣言。
void g(void pfa() throw(int)); // OK、関数へのポインタである引数の宣言。
typedef int (*pf)() throw(int); // エラー、 typedef 宣言。

[編集] 説明

関数がその例外指定の中に型 T を指定して宣言されているとき、その関数はその型またはその型から派生した型の例外を投げる可能性があります。

不完全型、 cv void* 以外の不完全型へのポインタまたは参照、および右辺値参照型は、例外指定に指定できません。 配列および関数型は (もし指定された場合) 対応するポインタ型に調節されます。 パラメータパックも使用できます。 (C++11以上)

関数がその例外指定に記載されていない型の例外を投げた場合は、関数 std::unexpected が呼ばれます。 デフォルトでは std::terminate を呼びますが、 (std::set_unexpected を介して) ユーザ定義の関数に置き換えることができ、 std::terminate を呼ぶまたは例外を投げることができます。 std::unexpected から投げられた例外が例外指定によって受理される場合は、スタックの巻き戻しが通常通りに続けられます。 そうでなく、 std::bad_exception が例外指定によって受理される場合は、 std::bad_exception が投げられます。 そうでなければ、 std::terminate が呼ばれます。

潜在的な例外

関数 f、関数へのポインタ pf、メンバ関数へのポインタ pmf は、それぞれ、投げられる可能性がある型から構成される潜在的な例外の集合を持ちます。 すべての型の集合はあらゆる例外が投げられる可能性があることを表します。 この集合は以下のように定義されます。

1) fpf または pmf の宣言が throw()(非推奨) または noexcept を用いている場合、集合は空です。
2) そうでなく、 fpf または pmf の宣言が動的例外指定(非推奨)を用いている場合、集合はその指定されている型から構成されます。
3) そうでなければ、集合はすべての型の集合です。

ノート: 暗黙に宣言された特別なメンバ関数 (コンストラクタ、代入演算子、およびデストラクタ) および継承コンストラクタについては、潜在的な例外の集合はそれらが呼び出すであろうすべてのもの (非変種非静的データメンバ、直接の基底、および (適切であれば) 仮想基底のコンストラクタ、代入演算子、デストラクタ (いつも通りデフォルト引数式を含みます)) の潜在的な例外の集合を合わせたものです。

e はそれぞれ潜在的な例外の集合を持ち、それは e の直接の部分式 (デフォルト引数式を含みます) のすべての潜在的な例外の集合の和に、以下のような e の形式に応じた別の集合を合わせたものです。

1) e が関数呼び出し式の場合、
  • その関数が id 式によって (メンバアクセスまたはメンバへのポインタアクセス式の一部として直接または間接的に) 表されている場合、その表されている関数の潜在的な例外の集合が一覧に追加されます。
  • その関数が noexcept 関数型の式または noexcept 関数へのポインタ型の式によって表されている場合、集合は空です。
  • そうでなければ、集合はすべての型の集合です。
2) e が暗黙に関数を呼ぶ (それが演算子式であって演算子がオーバーロードされている、それが new 式であって確保関数がオーバーロードされている、またはそれが完全式であって一時オブジェクトのデストラクタが呼ばれる) 場合、集合はその関数の集合です。
3) ethrow 式の場合、集合はその被演算子によって初期化されるであろう例外、または例外を投げ直す throw 式 (被演算子がない) の場合はすべての型の集合です。
4) e が多相型の参照への dynamic_cast の場合、集合は std::bad_typeid から構成されます。
5) e が多相 glvalue に適用される typeid の場合、集合は std::bad_typeid から構成されます。
6) e が非定数サイズの new 式の場合、集合はstd::bad_array_new_length から構成されます。
void f() throw(int);  // f() の集合は int です。
void g();             // g() の集合はすべての型の集合です。
struct A { A(); };    // new A の集合はすべての型の集合です。
struct B { B() noexcept; }; // B() の集合は空です。
struct D() { D() throw (double); }; // new D の集合はすべての型の集合です。

すべての暗黙に宣言されたメンバ変数 (および継承コンストラクタ) は以下のように選択された例外指定を持ちます。

  • 潜在的な例外の集合がすべての型の集合の場合、暗黙の例外指定は noexcept(false) です。
  • そうでなく、潜在的な例外の集合が空でない場合、暗黙の例外指定はその集合のすべての型の一覧です。
  • そうでなければ、暗黙の例外指定は noexcept(true) であり、関数の型は「noexcept 関数」です。
struct A {
    A(int = (A(5), 0)) noexcept;
    A(const A&) throw();
    A(A&&) throw();
    ~A() throw(X);
};
struct B {
    B() throw();
    B(const B&) = default; // 例外指定は「noexcept(true)」です。
    B(B&&, int = (throw Y(), 0)) noexcept;
    ~B() throw(Y);
};
int n = 7;
struct D : public A, public B {
    int * p = new (std::nothrow) int[n];
    // D は暗黙に宣言された以下のメンバを持ちます。
    // D::D() throw(X, std::bad_array_new_length);
    // D::D(const D&) noexcept(true);
    // D::D(D&&) throw(Y);
    // D::~D() throw(X, Y);
};
(C++17以上)

[編集]

#include <iostream>
#include <exception>
#include <cstdlib>
 
class X {};
class Y {};
class Z : public X {};
class W {};
 
void f() throw(X, Y) 
{
    int n = 0;
    if (n) throw X(); // OK。
    if (n) throw Z(); // これも OK。
    throw W(); // std::unexpected() を呼びます。
}
 
int main() {
  std::set_unexpected([]{
      std::cout << "That was unexpected" << std::endl; // フラッシュは必要です。
      std::abort();
  });
  f();
}

出力:

That was unexpected

[編集] 関連項目