C++のプロジェクトで、ロガー等にソースファイル名を渡したい場合、定義済みマクロの__FILE__
を渡すことが多いかと思います。
しかし__FILE__
の実装は環境依存であり、私がネットで調べた限りでは殆どの環境でフルパス名でした。当方の環境MSVC(_MSC_VER==1930)のC++20もまた然りでした。
このフルパス名からファイル名だけを抜き出すマクロの作り方をネットで調べると、概ね下記のような実装が紹介されています。
#define THIS_FILENAME (strrchr(__FILE__, '\\') ? strrchr( __FILE__, '\\' ) + 1 : __FILE__)
この方法でも問題なくファイル名の取得は出来るのですが、strrchr関数はコンパイル時評価が保証されていないため、実行の都度strrchrと条件分岐の判断が行われる可能性があります。
そこでフルパスからファイル名をコンパイル時に取得する方法を考えたので、拙劣ですが備忘録として記載します。以下はC++20のconsteval関数を使っております。
// ソースファイルのフルパスの文字列リテラルからファイル名だけ抽出
consteval std::string_view ExtractSourceFileNameFromFullpath( const char* fpath )
{
const std::string_view fname = fpath;
const auto pos_delim = fname.find_last_of( '\\' );
// const auto pos_fname = pos_delim != std::string::npos ? pos_delim - 1 : 0;
const auto pos_fname = pos_delim != std::string::npos ? pos_delim + 1 : 0;
// バグ修正2022/01/28
// 誤:pos_delim - 1
// 正:pos_delim + 1
const auto fn = std::string_view(
fname.data() + pos_fname,
fname.length() - pos_fname );
return fn;
}
#define THIS_FILENAME ExtractSourceFileNameFromFullpath( __FILE__ ).data()
上記の関数は、引数fpath(ファイルのフルパス名)を受け取り、ファイル名の部分だけを参照するstring_viewを返します。その関数をマクロTHIS_FILENAME
で置換します。
当初はconstexpr関数にしたのですが、当方の環境では静的評価しない場合があり、その条件が不明だったため、constevalにしたという経緯があります。条件さえ分かればconstexpr関数で問題ないかと思います。
更新履歴
2022/01/28 関数ExtractSourceFileNameFromFullpathのファイル名の先頭位置の計算が間違っておりました。これを修正しソース中にコメントを記述しました。大変失礼いたしました。