2024/5/31(金)

cpprefjpを読み進めた。

<source_location>

デバッグに超役立ちそうな素晴らしい機能。ついに__LINE__みたいなだるいやつを使う必要がなくなる。C++20から。

source_location

  • current: 現在位置を表すオブジェクトの取得。基本的には呼び出した行と一致するが、正しくは「オブジェクトが初期化される」
  • constructor: current()を使わずとも、無のsource_locationオブジェクトを作ることも可能らしい。type_infoは許可してなかったのに…
  • line, column, file_name, function_name: columnまであるのはすごい。

<exception>

stdexceptと別になっているのは、各種の例外vs例外の基礎的な機能という違いか。

  • exception
    • constructor, operator=: さすがに例外オブジェクトだからかnoexceptが付いている。
    • what: virtualが付いている。そりゃそう。
    • destructor: お前はnoexceptついてないのかよ!!なんで?
  • bad_exception: 動的例外仕様の削除の影響を(やや)受けている模様。今は例外オブジェクトのコピー失敗時のみ出てくる、のか?
  • set_unexpected, get_unexpected, unexpected: 動的例外仕様が削除されたのでお役御免に。
  • terminate, set_terminate, get_terminate: abortとの違いを初めて認識した。例外処理でおかしなことが起こった場合専用の異常終了という立ち位置らしい。しかしこれ、基本的にシステムから呼び出されるものならユーザーがterminate()を呼び出せる意味はあるのか?
  • nested_exception: ちょっと分かりにくいが、例外処理中にこれを投げれば現在処理中の例外を内包してくれるらしい。ということでnested_exceptionを継承した自作例外クラスを作れば、それを例外処理中に投げることで自動的にそこで本来処理されていた例外の情報を保持できるという訳だ。単に別の例外を再スローするよりも正確なエラー情報を呼び出し元に引き継げる。
  • uncaught_exception, uncaught_exceptions: 今例外処理中かどうかなんて大体は文脈で分かるだろうし、分からない文脈では例外処理中かどうかなんて知っても何も変わらないのでは??みたいな気がするが、これが必要になるユースケースもあるんだろうか。ネットで出てきた例としては、デバッグログに役立てるというのは1つあるようだ。
  • exception_ptr: 例外オブジェクトを多スレッド間などで持ちまわるのに使えるらしい。サブスレッドで例外が起きて異常終了する際にメインスレッドでログを吐く、みたいなケースでは使えるのかもしれない。
  • current_exception: これもuncaught_exceptions同様「知ってどうする」感があるが、どうやらこれを使うとexception_ptrにくるまれるらしい。
  • rethrow_exception: throw;じゃいかんのか??と思うが、例外をexception_ptrで持ちまわっていた場合はこれが好都合なのか。
  • make_exception_ptr: はい
  • throw_with_nested: 普通にnested_exceptionを継承したクラスをスローするのでよくないか。
  • rethrow_if_nested: 外側の例外を処理した上で、処理しなければいけない内側のものがあればスロー、ということなのだろうが、その場で処理しているのにわざわざ上に処理を再度投げることがあるだろうか?若干疑問に思うが、「ある特定の例外オブジェクトを受け取ってそれ専用の後処理をする」というcatch節であれば割と納得が行くかもしれない。

読んでみて初めて認識したが、「例外の入れ子」「exception_ptrによる例外オブジェクトの持ち回り」というのが結構重要な位置づけになっているように見える。自分はかなり雑なエラー処理しか書いたことがないので使ったことが無かったが、正確なエラー情報を伝播させるためには必須なのだろう。

Categories: