1x系は刺激的で楽しい。
そんな刺激的な中で何も変わっていないものが普通の assert。
コンパイルタイムで利用できる static_assert が追加され、メッセージも別途出力できるのに
こいつだけは何も変わっていない!
assert(false && "hoge"); assert(!"foo");
泥臭くていやなんです。
ということで、何番煎じかは置いといて「無ければ作ればよろし」。
前提としては、
(1) メモリがシビアではない環境
(2) メッセージの別途出力(stream風に記述したい)
(3) リリースモードで一命令も吐かせない
(4) リリースモードでコンパイラを黙らせる(C4101対策)
bool cond = false; int value = 10; assert(cond, "hoge: " << value);
上記のような感じが目標。
#pragma once #include <iostream> #include <sstream> #undef ASSERT_MSG #undef ASSERT #ifdef NDEBUG #define ASSERT_MSG(expression, message)\ do{\ (void)(true ? (void)0 : ((void)(expression)));\ (void)(true ? (void)0 : ((void)(std::ostringstream() << message)));\ }while(false) #define ASSERT(expression)\ ASSERT_MSG(expression, "") #else #define ASSERT_MSG(expression, message)\ do{\ if(!(expression)){\ std::cerr << "Assertion `" #expression "` failed in " << __func__ << "() " << __FILE__ << "(" << __LINE__ << "): " << message << std::endl;\ std::terminate();\ }\ }while(false) #define ASSERT(expression)\ ASSERT_MSG(expression, "") #endif
そしてこんな感じ。
bool cond = false; int value = 10; ASSERT_MSG(cond, "hoge" << value);
STL(std::ostringstream())はコンパイルタイムで対処しないとコードが生成されるため
当初は、(void)sizeof() などを利用したが、その他のケースを両立できないため
シンプルにコンパイラに丸投げすることに。
msvs2015環境では前提条件をすべて満たしたことは確認。
コンパイラさんの最適化恐るべし。