このプロジェクトでは、printf 互換関数を使用して、外部ログ ファイルにメッセージを追加します。例えば、私たちは書くことができます
__LOG_INFO( "number of files = %d\n", number_of_files );
__LOG_INFO( "Just for information\n" );
の関数宣言は次の__LOG_INFO
ようになります
template<int N>
inline void __LOG_INFO( const char (&fmt)[N] )
{
call_printf( MODULE_NAME, fmt, debug_parameters() );
}
template<int N, typename T1>
static void __LOG_INFO( const char (&fmt)[N], const T1 &t1 )
{
call_printf( MODULE_NAME, fmt, debug_parameters( t1 ) );
}
template<int N, typename T1, typename T2>
static void __LOG_INFO( const char (&fmt)[N], const T1 &t1, const T2 &t2 )
{
call_printf( MODULE_NAME, fmt, debug_parameters( t1, t2 ) );
}
...
ここで、C++ 11 constexpr 機能を使用してコンパイル時のフォーマット文字列チェックをいくつか追加したいと考えています。たとえば、フォーマット文字列のパラメーター数を非常に簡単にチェックするには、この関数を使用します。
template<int N>
constexpr static int count_arguments( const char (&fmt)[N], int pos = 0, int num_arguments = 0 )
{
return pos >= N-2 ? num_arguments :
fmt[pos] == '%' && fmt[pos+1] != '%' ? count_arguments( fmt, pos+1, num_arguments+1 ) :
count_arguments( fmt, pos+1, num_arguments );
}
__LOG_INFO
ここでの問題は、コンパイラが fmt が整数定数ではないと文句を言うため、関数自体の内部に static_assert のようなものを追加できないことです。だから今、私たちはこの醜いマクロソリューションを持っています:
#define COUNT_ARGS(...) COUNT_ARGS_(,##__VA_ARGS__,8,7,6,5,4,3,2,1,0)
#define COUNT_ARGS_(z,a,b,c,d,e,f,g,h,cnt,...) cnt
#define LOG_INFO(a, ...) \
{ \
static_assert( count_arguments(a)==COUNT_ARGS(__VA_ARGS__), "wrong number of arguments in format string" ); \
__LOG_INFO(a,##__VA_ARGS__); \
}
したがって、 を呼び出す代わりに、 を呼び出す__LOG_INFO
必要がありますLOG_INFO
。
上記のマクロを使用する以外に、より良い解決策はありますか?