はじめに
この記事は、
Siv3D Advent Calendar 2022
https://qiita.com/advent-calendar/2022/siv3d
2日目の参加記事です。
Siv3Dで、ある値とその"ソースコード上の位置"を出力する関数を作ります。
Rustのdbg!って何
Rust言語のマクロです。こういうコードを書くと、
Playground
fn f() -> i32 {
1225
}
fn main(){
let xmas = (12, 25);
dbg!(xmas);
dbg!(f());
}
こういう標準エラー出力をしてくれます。
(この記事ではRustについてはこれ以上触れません)
[src/main.rs:7] xmas = (
12,
25,
)
[src/main.rs:8] f() = 1225
タネと仕掛け
std::source_location
というクラスがC++20で標準ライブラリに追加されました。
何らかの関数F
のデフォルト引数にsource_location::current()
を指定すると、
F
を呼び出した位置を表すsource_location
オブジェクトが得られるようになっています。
参考:
- source_location - cpprefjp C++日本語リファレンス
https://cpprefjp.github.io/reference/source_location/source_location.html - source_location::current - cpprefjp C++日本語リファレンス
https://cpprefjp.github.io/reference/source_location/source_location/current.html
環境
- OpenSiv3D v0.6.5 (Win)
- OpenSiv3D v0.6.6 (Win)
- (未確認ですがv0.6以降なら大丈夫な気がします)
- 結局
std::source_location
が今回の本質なので
- 結局
code (& sample)
# include <Siv3D.hpp> // OpenSiv3D v0.6.5
# include "dbg.hpp"
void fnA()
{
dbg(U"dbg test");
dbg(Scene::Time());
}
void Main()
{
int sum = 0;
while (System::Update())
{
if (KeyA.down())
{
fnA();
sum += dbg(Random(5));
dbg(sum);
}
if (KeyC.down())
{
dbg(U"Console test", Console);
}
}
}
# pragma once
# include <source_location>
template<class Output = decltype(s3d::Print)>
auto dbg(
Output output = s3d::Print,
std::source_location loc = std::source_location::current()
) {
auto text = U"[{}:{}:{} {}] "_fmt(
FileSystem::RelativePath(Unicode::Widen(loc.file_name())),
loc.line(),
loc.column(),
Unicode::Widen(loc.function_name())
);
return std::move(output << text);
}
template<class Output = decltype(s3d::Print), s3d::Concept::Formattable Formattable>
auto&& dbg(
Formattable&& item,
Output output = s3d::Print,
std::source_location loc = std::source_location::current()
) {
dbg(output, loc) << item;
return item;
}
コメント
- tupleを使えば複数アイテムをdbg()1回で出力できます
- outputにはSiv3Dの各種出力の使用を想定しています
-
Print
(画面出力) -
Console
(コンソール出力) -
Logger
(ログ出力) - (
Say
(音声読み上げ)) - チュートリアル 01 | Siv3D の基本|Siv3D リファレンス v0.6.5
1.10 Print 以外の出力
https://zenn.dev/reputeless/books/siv3d-documentation/viewer/tutorial-basic#1.10-print-%E4%BB%A5%E5%A4%96%E3%81%AE%E5%87%BA%E5%8A%9B
-
- 他のテンプレート引数と併用したかったので
SIV3D_CONCEPT_FORMATTABLE
ではなくs3d::Concept::Formattable
を使用していますが
どうせsource_location
がC++20からなので問題ないと思っています
おわりに
色々なオブジェクトの出力関数が初めから定義されているということでSiv3Dベースで進めてきましたが、
std::cout, cerr
等にも応用できるはずです。
というか標準エラー向けなら高機能なライブラリがgithubにありました。
sharkdp/dbg-macro: A dbg(…) macro for C++
https://github.com/sharkdp/dbg-macro
参考文献
- source_location - cpprefjp C++日本語リファレンス
https://cpprefjp.github.io/reference/source_location/source_location.html - source_location::current - cpprefjp C++日本語リファレンス
https://cpprefjp.github.io/reference/source_location/source_location/current.html - チュートリアル 01 | Siv3D の基本|Siv3D リファレンス v0.6.5
1.10 Print 以外の出力
https://zenn.dev/reputeless/books/siv3d-documentation/viewer/tutorial-basic#1.10-print-%E4%BB%A5%E5%A4%96%E3%81%AE%E5%87%BA%E5%8A%9B