LoginSignup
5
2

More than 1 year has passed since last update.

C++20でRustのdbg!っぽく

Last updated at Posted at 2022-12-01

はじめに

この記事は、
Siv3D Advent Calendar 2022
https://qiita.com/advent-calendar/2022/siv3d
2日目の参加記事です。

Siv3Dで、ある値とその"ソースコード上の位置"を出力する関数を作ります。

Rustのdbg!って何

Rust言語のマクロです。こういうコードを書くと、
Playground

main.rs
fn f() -> i32 {
    1225
}
fn main(){
    let xmas = (12, 25);
    dbg!(xmas);
    dbg!(f());
}

こういう標準エラー出力をしてくれます。
(この記事ではRustについてはこれ以上触れません)

stderr
[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オブジェクトが得られるようになっています。

参考:

環境

  • OpenSiv3D v0.6.5 (Win)
  • OpenSiv3D v0.6.6 (Win)
  • (未確認ですがv0.6以降なら大丈夫な気がします)
    • 結局std::source_locationが今回の本質なので

code (& sample)

sample.cpp
# 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);
		}
	}
}

dbg.hpp
# 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;
}

スクリーンショット(Aキーを3回押した):20221113-152123-516.png

コメント

  • tupleを使えば複数アイテムをdbg()1回で出力できます
  • outputにはSiv3Dの各種出力の使用を想定しています
  • 他のテンプレート引数と併用したかったので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

参考文献

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2