次のかなり単純なクラスを想定します。
struct A {
bool toBool() const { return true; }
template<typename T> T to() const { return T();}
};
ここで、次の存在をテストしたいと思いますtoBool
。
template<typename From, typename To>
class has_toBool_func
{
typedef char (&Two)[2];
template<typename F, bool (F::*)() const> struct helper {};
template<typename F> static char test(helper<F, &F::toBool>*);
template<typename F> static Two test(...);
public:
static const bool value = (sizeof(test<From>(0)) == sizeof(char));
};
が定義され、使用されます。
::std::cout << "int: " << has_toBool_func<int, bool>::value
<< ", A: " << has_toBool_func<A, bool>::value << ::std::endl;
そして、期待される出力 "int: 0, A: 1" だけが生成されます。
関数テンプレートに対して同じことを試してみてください:
class has_to_func
{
typedef char (&Two)[2];
template<typename F, To (F::*)() const> struct helper {};
template<typename F> static char test(helper<F, &F::to<To> >*);
template<typename F> static Two test(...);
public:
static const bool value = (sizeof(test<From>(0)) == sizeof(char));
};
::std::cout << "int: " << has_to_func<int, bool>::value
<< ", A: " << has_to_func<A, bool>::value << ::std::endl;
期待される出力 "int: 0, A: 1" ではなく、コンパイル エラーが発生します。
なぜこうなった?そしてもちろん:どうすれば修正できますか?
MSVC 2012
警告を与える
warning C4346: 'F::to' : dependent name is not a type
prefix with 'typename' to indicate a type
see reference to class template instantiation 'xtd::has_to_func<From,To>' being compiled
従属名は実際にはタイプではなくエラーであるため、これは役に立ちません
error C2998: 'char test' : cannot be a template definition
これもあまり役に立ちません...
ICC13.0
最初にエラーを与える
error : type name is not allowed
template<typename F> static char test(helper<F, &F::to<To>() >*);
(<To>
はマークされています)
これは問題を説明していますが、なぜこれが発生したのか、別のエラーが発生したのかについては完全にわかりません
error : expected a ")"
template<typename F> static char test(helper<F, &F::to<To>() >*);
(最後>
に印がついています)
これは完全なぼろぼろであり、コンパイラが混乱したためにのみ表示されていると確信しています。