型名を受け取ることを想定する以下のようなマクロがあるとします.
#define MACRO(TYPE) .....
このようなマクロに対してテンプレート引数を伴った型名を指定すると問題が起きます.
MACRO(std::vector<int, my_allocator<int> >)
このマクロの呼び出しは第1引数を"std::vector
MACRO((std::vector<int, my_allocator<int> >))
としてやれば,"(std::vector
型名の周りに(余計な)カッコを許す構文は非常に限られています.1つは関数の仮引数の型名です.これを使って上の問題を部分的に解くことができます.
#define MACRO(TYPE) boost::function_traits<void TYPE>::arg1_type MACRO((std::vector<int, my_allocator<int> >)) // std::vector<int, my_allocator<int> >が取り出せる
この解法の欠点は,指定した型が正確に取り出せるわけではなく指定した型のDecayed Typeが取り出されるという点です.もちろん多くの型においてはそのままの形で取り出せますが.
BoostにおいてはBoost.Interface(正確にはBoostに提案中のライブラリであり,Boostの一部ではありません)のBOOST_IDL_PROTECTにこの手法を見ることができます.
この問題に対するより好ましい解法はC99にあるような可変引数マクロ(Variadic Macro)を利用することですが,現在のC++の標準にはそのような可変引数マクロの構文はありません.Boost.Waveではそのようなマクロ構文が導入されており,将来的にC++0xにも導入される予定です.