foo
(prints 0)のパラメータにテンプレートメソッドisA<void>
がある場合は、struct A
の1つの関数foo
を残そうとしています。このコードはコンパイルされ(gcc 6.1.0とclang-3.9.0で明示的に--std=c++14
オプションが指定されています)、実行されます。この場合、SFINAEが正しく動作しないのはなぜですか?
しかし、それは1を出力しますが、私はそれが0を出力することを確信しています。私はどこが間違っているのだろうかと疑問に思うが、実際の質問は正しい。
C++ 14ソリューションのみをご利用ください。
#include <type_traits>
#include <iostream>
#include <utility>
using std::enable_if;
using std::declval;
using std::true_type;
using std::false_type;
using std::cout;
template<int M>
struct ObjectX
{
template<typename C>
bool isA() { return false; }
};
struct XX : ObjectX<23456> {
int af;
};
template <typename ObjType> using has_dep = decltype(declval<ObjType>().template isA<void>());
template <typename, typename = void>
struct has_isa : public false_type {};
template <typename ObjType>
struct has_isa<ObjType, has_dep<ObjType> > : public true_type {};
template<typename ObjType>
struct A
{
template<typename T = void>
typename enable_if<has_isa<ObjType>::value, T>::type
foo() {
cout << "called foo #0" << "\n";
}
template<typename T = void>
typename enable_if<!has_isa<ObjType>::value, T>::type
foo() {
cout << "called foo #1" << "\n";
}
};
int
main()
{
A<XX> axx;
// XX().template isA<void>(); -- to check, that we can call it and it exists
axx.foo();
return 0;
}
2番目のテンプレートパラメータを指定しないと、 'has_isa'は' void'を持つものの代わりに自動的に 'has_dep'を使って特殊化を試みません。 – Albjenow
@Albjenowこの方法は、関数メンバがテンプレートでない場合に機能します。コードを少し変更してみて(テンプレートCを削除してhas_depを修正してください)、それ以外のものがすべて正しいことがわかります。より限定されたスペシャライゼーションが常に制限の少ないものに勝つので、それをしようとします –