最終更新日時:
が更新

履歴 編集

function template
<exception>

std::rethrow_if_nested(C++11)

namespace std {
  template <class E>
  void rethrow_if_nested(const E& e); // (1) C++11
}

概要

入れ子になった例外が存在する場合に、入れ子になった例外を送出する

効果

  • Eが多相的(polymorphic)なクラス型でない場合、またはnested_exceptionEのアクセス不能もしくは曖昧な基底クラスである場合、何もしない。
  • そうでなければ、以下を行う:

    if (auto p = dynamic_cast<const nested_exception*>(addressof(e)))
      p->rethrow_nested();
    

戻り値

なし

#include <iostream>
#include <exception>
#include <memory>

struct inner_error : public std::exception {};
struct outer_error : public std::nested_exception {};

// 現在の例外を取得
template <class T>
std::shared_ptr<T> get_exception(std::exception_ptr ep)
{
  try {
    std::rethrow_exception(ep);
  }
  catch (T& e) {
    return std::shared_ptr<T>(new T(e));
  }
  catch (...) {}
  return nullptr;
}

// 入れ子になってる例外を取得
template <class T>
std::shared_ptr<T> get_nested_exception(std::nested_exception& ex)
{
  try {
    std::rethrow_if_nested(ex); // 入れ子になってる例外を送出
  }
  catch (T& e) {
    return std::shared_ptr<T>(new T(e));
  }
  catch (...) {}
  return nullptr;
}

int main()
{
  try {
    try {
      throw inner_error();
    }
    catch (...) {
      // inner_errorを入れ子にしてouter_errorを送出
      std::throw_with_nested(outer_error());
    }
  }
  catch (...) {
    // 外側の例外を取得
    if (std::shared_ptr<outer_error> outer = get_exception<outer_error>(std::current_exception())) {
      std::cout << "outer" << std::endl;

      // 入れ子になった例外を取得
      if (std::shared_ptr<inner_error> inner = get_nested_exception<inner_error>(*outer)) {
        std::cout << "inner" << std::endl;
      }
    }
  }
}

出力

outer
inner

バージョン

言語

  • C++11

処理系

関連項目

参照

  • P3842R2 A conservative fix for constexpr uncaught_exceptions() and current_exception()
    • C++26の策定中にconstexprが追加されたが、本提案文書により巻き戻された (C++29で再検討予定)
  • LWG Issue 2484. rethrow_if_nested() is doubly unimplementable
    • Eが多相的でない場合は何もしないこと、およびeの静的型がnested_exceptionであるかそこからpublicかつ曖昧さなく派生している場合を対象とすることが規定された
    • この修正は欠陥報告(DR)であり、C++11以降に遡及して適用される。 C++11時点の規定は「eの動的型がnested_exceptionから派生しているか」で判定するとしていたが、非多相なクラス型では動的型を判別するdynamic_cast自体が不適格となるため、規定どおりに実装することが不可能だった。したがって処理系は当初からこの修正後の挙動(非多相型では何もしない)を採るしかなく、これと異なる観測可能な挙動が出荷されていたわけではない
  • LWG Issue 2784. Resolution to LWG 2484 is missing "otherwise, no effects" and is hard to parse
    • LWG 2484の解決を整理し、静的型の判定と動的型の判定を分離して、効果をポインタ版dynamic_castとヌルチェックを用いる形に書き直した。あわせて、条件を満たさない場合は何もしないことが明記された
    • この修正も欠陥報告(DR)であり、C++11以降に遡及して適用される。 LWG 2484と同じ規定を読みやすく書き換えたものであり、意図された挙動は変わらないため