次の C++ コードは、MS Visual Studio 2010 ではコンパイルされません。
class Foo
{
public:
/// Provides the signature of the methods that can be given to addValueSetListener
template <typename TT>
struct ChangeHandler
{
typedef void ( TT::* OnSetValueMethod )();
};
template <typename TT>
void bar_ok(TT*, void ( TT::* )(), bool = false) {}
template <typename TT>
void bar_ok(const char*, TT*, void ( TT::* )()) {}
template <typename TT>
void bar_fails(TT*, typename ChangeHandler<TT>::OnSetValueMethod, bool = false) {}
template <typename TT>
void bar_fails(const char*, TT*, typename ChangeHandler<TT>::OnSetValueMethod) {}
void testBar() {}
};
int main()
{
Foo foo;
foo.bar_ok ("allo",& foo, & Foo::testBar); // compiles
foo.bar_fails("allo",& foo, & Foo::testBar); // compile ERROR
}
'TT': must be a class or namespace when followed by '::'
ERROR 行のコンパイラ エラーはです。
失敗する行と失敗しない行の唯一の違いは、bar_fails がvoid (TT::*)()
「テンプレート化された typedef」を介して「メソッド ポインター型」引数を宣言しているのに対し、bar_ok はそれを直接宣言していることです。
const char*
のオーバーロードがなければ、テンプレート化された typedef は正常に機能することに注意してください。const char* オーバーロードが使用可能な場合、コンパイラは誤ってTT=[const char]
bar_fails のオーバーロードを選択しますが、bar_ok の TT=Foo オーバーロードを正しく選択します。typedef が TT* や float* のような「単純な」データ用である場合、この問題は発生しません。