C++0x の nested_exception について 其の壱(仕様)

[C++] C++WGアドホック会議レポート - Faith and Brave - C++で遊ぼう で、挙がっている nested_exception の問題ですが、まずは第一の認識合わせとして関連箇所のドラフトを邦訳しました。間違い等を発見されましたら適宜修正しますのでご指摘願います。次のステップとして 2003 ベースの仕様に準拠しているコンパイラで利用可能な nested_exception の実装を現在、準備中です。


§18.7.5 例外伝播(Exception Propagation) [propagation]

typedef unspecified exception_ptr;

1 exception_ptr の型は例外オブジェクトを参照するのに使用することができるよ。
2 exception_ptr は DefaultConstructible(引数なしで構築可能), CopyConstructible(複写構築可能), Assignable(代入可能), EqualityComparable(等価比較可能) だよ。exception_ptr の操作には例外送出が伴わないよ。
3 exception_ptr 型の二つのオブジェクトは、それらが同じ例外を参照している場合に限り、等価比較において等しくなるよ。
4 exception_ptr のデフォルトコンストラクタは、null 値で初期化を行うよ。 null 値はそれ自身とのみ等価になるよ。
5 exception_ptr 型のオブジェクトは null ポインター定数との等価比較と null ポインター定数の代入ができるよ。その効果により exception_ptr() はあたかも null ポインター定数のように使えるよ。
6 [注意: 実装により、exception_ptr として参照カウント付きスマートポインタが使われる可能性があるよ。 ―注意]

exception_ptr current_exception();

7 戻り値: 現在処理している例外もしくはその複製を参照している exception_ptr オブジェクトあるいは、処理中の例外が無い場合には null exception_ptr オブジェクトを返すよ。参照されているオブジェクトは少なくとも exception_ptr によって参照されている間は有効であるべきだよ。この関数がメモリの確保を必要としそしてその試みが失敗した場合、bad_alloc のインスタンスを参照した exception_ptr オブジェクトを返すよ。二回の成功した current_exception() の呼び出しによる戻り値が参照している例外オブジェクトが同じであるかは未定義だよ。[注意: これは、current_exception() が新しい複製をそれぞれが呼び出される度に作成するかどうかが未定義である為だよ。 ―注意] 現在の例外オブジェクトを複製しようとして例外が送出された場合、この関数はを送出された例外、それが不可能であれば bad_exception のインスタンスを参照している exception_ptr オブジェクトを返すよ。[注意: 送出された例外の複写構築もまた失敗するかもしれないので、無限再帰を回避する為に bad_exception で代用する実装が許されるよ。 ―注意]
8 例外は送出しないよ。

void rethrow_exception(exception_ptr p);

9 p が null ポインタでないことを要求するよ。
10 p が参照している例外オブジェクトを送出するよ。

template<class E> exception_ptr copy_exception(E e);

11 効果: 次のコードのような効果があるよ。

  try {
    throw e;
  } catch(...) {
    return current_exception();
  }

12 [注意: この関数は利便性と効率のために提供されるよ。 ―注意]

§18.7.6 nested_exception [except.nested]

namespace std
{
    class nested_exception
    {
    public:
        nested_exception() throw();
        nested_exception(const nested_exception&) throw() = default;
        nested_exception& operator=(const nested_exception&) throw() = default;
        virtual ~nested_exception() = default;
        
        // access functions
        void rethrow_nested() const; // [[noreturn]]
        exception_ptr nested_ptr() const;
    };
    template<class T> void throw_with_nested(T&& t); // [[noreturn]]
    template <class E> void rethrow_if_nested(const E& e);
}

1 nested_exception クラスは多重継承の mixin として使用されるように設計されているよ。このクラスは現在扱っている例外を補足し、後で使う為に格納するよ。
2 [注意: nested_exception は多様クラスを作れるように仮想デストラクタを持っているよ。その存在は dynamic_cast で確かめることができるよ。 ―注意]

nested_exception() throw();

3 効果: このコンストラクタは current_exception() を呼び出し、返り値を格納するよ。

void rethrow_nested() const; // [[noreturn]]

4 その nested_exception クラスのオブジェクトに補足され格納されている例外を送出(throw)するよ。

exception_ptr nested_ptr() const;

5 その nested_exception クラスのオブジェクトに補足され格納されている例外を返すよ。

template <class T> void throw_with_nested(T&& t); // [[noreturn]]

6 T が CopyConstructible であることを要求するよ。
7 T が nested_exception から派生されていない型の場合、T と nested_exception の両方から public に派生している未定義の例外を送出(throw)し、そうでなければ t を送出(throw)するよ。

template <class E> void rethrow_if_nested(const E& e);

8 効果: e が public に nested_exception から派生されている場合にのみ e.rethrow_nested() を呼び出すよ。

...で、ちょっと心配なのが§18.7.5¶3で言う「同じ例外」でして、「同じ例外オブジェクト」のことだろうと私は解釈しているのですが、ひょっとしたら「同じ例外型」のことかもしれません。( 他の箇所では比較的、型のことを言ってるのかオブジェクトのことを言ってるのかがはっきりと明示されているのですが、ここは記述が曖昧です。 )