問題:
私は可変個引数マクロを書きたいと思っています
#define WRAP(token, ...)
これは、トークンと N 個の引数で呼び出された場合
WRAP(decltype, a, b, c)
トークンにラップされた引数のコンマ区切りリストに展開されます
decltype(a), decltype(b), decltype(c)
これにより、次のようなものを書くことができます。
#define MACRO(...) \
Class< WRAP(decltype, __VA_ARGS__) >::Function();
次のように呼び出すと:
MACRO(a, b, c)
次のようになります。
Class<decltype(a), decltype(b), decltype(c)>::Function(0;
これを達成する方法がわかりません。出来ますか?おそらく、BOOST_PP
またはそのようなものでしょうか?
動機:
ログ用のマクロがあります:
#define LOG(fmt, ...) \
logger::instance().push(__FUNCTION__, fmt, __VA_ARGS__);
引数が提供されたフォーマット文字列と一致することを確認できる可変個引数クラス テンプレートがあります。
template<typename... Ts>
struct Format
{
template<std::size_t N>
static constexpr bool check(const char (&fmt)[N], std::size_t n);
};
固定数の引数でマクロを定義すると、フォーマット チェック関数を呼び出すことができます。
#define LOG(fmt, a) \
static_assert(Format<decltype(a1)>::check(fmt, 0), ""); \
logger::instance().push(__FUNCTION__, fmt, a);
ただし、可変引数マクロを使用すると、これは複数の引数に対しては機能しません。
#define LOG(fmt, ...) \
static_assert(Format<decltype(__VA_ARGS__)>::check(fmt, 0), ""); \
logger::instance().push(__FUNCTION__, fmt, __VA_ARGS__);
これdecltype(__VA_ARGS__)
は、明らかに無効な構文であるためです。
それを修正するには、展開する必要があり__VA_ARGS__
ますdecltype(a1), decltype(a2), decltype(a3)
可変関数テンプレート?
constexpr
可変引数関数テンプレートを使用してこれを達成しようとしましたが、この時点で文字列リテラルではなくなったためfmt
、 a に渡すことができません。static_assert
template<size_t N, typename... Ts>
constexpr void check(const char (&fmt)[N], const Ts&...)
{
static_assert(Format<Ts...>::check(fmt, 0), "");
}
このチェック関数を呼び出そうとしています
check("%s", "hello world");
コンパイルに失敗します:
main.cpp:216:46: in constexpr expansion of ‘Format<T, Ts ...>::check<7ul>((* & fmt), 0ul)’
main.cpp:216:5: error: ‘fmt’ is not a constant expression