plusctx (処理履歴の保存と参照)
ライブラリというよりは実装アイデアという感じ。ロギングの課題を解決するために考えていところ、構造的に割と面白かったので組んでみた。
組んだ後でスタックトレースで良いのでは?とも思ったけど、まあ、マルチプラットフォームで取ったり、整形したり、任意の情報乗っけたりとか考えたら、一応用途はありそう。
- https://github.com/kkAyataka/plusctx
- より下位の関数内で、どの関数から (どういったコンテキストで) 呼び出されたかを取得できる
- 自前のスタックトレースのような感じ
- ロギング用途を想定
サンプル
- 関数の冒頭で
PLUSCTX_CTX("name");
としてコンテキストを定義する- コンテキストはスレッド毎 (thread_local) にスタックとして保存される
- ブロックコープを抜けると (関数を抜けると) スタックから破棄される
- サブ関数内でコンテキストスタックを確認すると、上位の (呼び出し元) の情報を得ることができる
#include "plusctx/plusctx.hpp" #include <iostream> #include <sstream> // コンテキストスタックから文字列を生成 // スタックはスレッド毎に管理 std::string get_ctx_string() { const auto stack = plusctx::get_context_stack(); std::ostringstream ss; for (const auto c : stack) { ss << ">" << c->name; } return ss.str(); } void sub1(); // main int main() { PLUSCTX_CTX("main"); // mainを詰んだのでmainだけ std::cout << get_ctx_string() << std::endl; // >main sub1(); // コンテキストの寿命はブロック単位なので、 // sub1コンテキストは削除されてる std::cout << get_ctx_string() << std::endl; // >main } void sub1() { PLUSCTX_CTX("sub1"); // mainから呼び出されたことがわかる std::cout << get_ctx_string() << std::endl; // >main>sub1 }
plusctx::Contextクラス
ロギング用途を想定しているので、コンテキストには関数名やファイル名などを保存している。コンテキスト情報の取り扱いについては既定していないので、どう使うかは別の問題。
// 任意の名前だけでなく、関数名やファイル名も保存する class Context { public: Context( const std::string name, const std::string func_name, const std::string rich_func_name, const std::string file_name, const std::size_t line_no ); // 簡易にインスタンス化できるようにマクロを準備 #define PLUSCTX_CTX(name) plusctx::Context plusctx_ctx__( \ name, \ __func__, \ __FUNCSIG__, \ plusctx::detail::shorten_file_name(__FILE__), \ __LINE__)