関数の仮引数として指定した型は規格(8.3.5/3)に従って一定の変更を受けます.例えば配列型はポインタ型に,関数型は関数へのポインタ型に読み替えられます.このような変更を受けた型は元の型のDecayed Typeと呼ばれます.
Decayed Typeが出てくる文脈としては汎用関数に文字列定数を直接渡すときに推論される型の調整や,マクロの引数として型を渡すときの「むき出しのコンマの問題」(以下参照)があります.
マクロにおけるむき出しのコンマの問題
型名を受け取ることを想定する以下のようなマクロがあるとします.
#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にも導入される予定です.