4

C++11 仕様では、暗黙的に生成された特殊関数 (つまり、既定のコンストラクタ、デストラクタ、コピー/移動コンストラクタ、およびコピー/移動代入演算子) に例外仕様があることは明らかです。しかし、この仕様は、現在は推奨されていない動的例外仕様 (つまり、「throw (T1, T2, T3)」)に関してのみ記述されているようです。これは、15.4/14 の例で裏付けられています。

struct A {
  A();
  A(const A&) throw();
  A(A&&) throw();
  ~A() throw(X);
};
struct B {
  B() throw();
  B(const B&) throw();
  B(B&&) throw(Y);
  ~B() throw(Y);
};
struct D : public A, public B {
  // Implicit declaration of D::D();
  // Implicit declaration of D::D(const D&) throw();
  // Implicit declaration of D::D(D&&) throw(Y);
  // Implicit declaration of D::D() throw(X, Y);
};

注記は規範的ではありませんが、D のコピー コンストラクターが のthrow()代わりに宣言されていることは注目に値しnoexceptます。throw()aに違反している場合と a に違反している場合では、プログラムの動作が異なるため、違いが生じnoexceptます。

例の上の 15.4/14 のテキストは規範的であり、次のように述べています。

暗黙的に宣言された特別なメンバー関数 (第 12 節) には、例外仕様が必要です。f が暗黙的に宣言されたデフォルト コンストラクター、コピー コンストラクター、ムーブ コンストラクター、デストラクタ、コピー代入演算子、またはムーブ代入演算子である場合、その暗黙的な例外指定は、例外指定によって T が許可されている場合にのみ、型 ID T を指定します。 f の暗黙の定義によって直接呼び出される関数。f が直接呼び出す関数がすべての例外を許可する場合、f はすべての例外を許可し、f が直接呼び出すすべての関数が例外を許可しない場合、f は例外を許可しません。

ここでは動的な例外仕様のみが参照されていることを考えると、暗黙的に生成された特別なメンバー関数は決して宣言されないのではないかと心配していnoexceptます。本当にそうですか?

4

1 に答える 1

1

そんなことはないと思います。実際の要件は、「...f が直接呼び出すすべての関数が例外を許可しない場合、例外を許可しない」ということだけです。

上記のとおり (§15.4/12):

定数式がを生成するthrow()noexcept、またはnoexcept(定数式の形式である場合、例外仕様は非スローです。非スローの例外仕様を持つ関数は、例外を許可しません。)true

非スロー例外仕様が例外を許可しないということは、正確には啓示ではありませんが、非スロー例外仕様の説明の文言が、暗黙的に宣言された特別なメンバー関数の要件にほぼそのまま反映されていることを示していると思います。 . throw()そのため、スローしない例外指定 (またはnoexceptまたは)の任意の形式noexcept(<anything that converts to true>)が許可されているように見えます。これは、言葉遣いの偶然ではなく、具体的に意図されたものです。

于 2012-10-24T06:38:54.817 に答える