テンプレートのメタプログラミング コードを書くのは初めてです (それを読むだけではありません)。だから私はいくつかの初心者の問題に反抗しています。そのうちの 1 つは、 「私の SFINAE に何が起こったのですか?」というSO 以外の投稿でかなりよく要約されています。、これを次のように C++11 化します。
(注: この「思考実験」の例では、エラーの診断に役立つようにメソッドに異なる名前を付けました。非オーバーロードに対して実際にこのアプローチを実際に選択しない理由については、@R.MartinhoFernandes のメモを参照してください。)
#include <type_traits>
using namespace std;
template <typename T>
struct Foo {
typename enable_if<is_pointer<T>::value, void>::type
valid_if_pointer(T) const { }
typename disable_if<is_pointer<T>::value, void>::type
valid_if_not_pointer(T) const { }
};
int main(int argc, char * argv[])
{
int someInt = 1020;
Foo<int*>().valid_if_pointer(&someInt);
Foo<int>().valid_if_not_pointer(304);
return 0;
}
@Alfは、SFINAEに何が起こったのか「そもそもそこになかった」と述べ、コンパイルすることを提案しますが、クラスの代わりに関数をテンプレート化します。これは状況によっては適切かもしれませんが、すべてではありません。 (たとえば、コピー構築可能かどうかに関係なく型を保持できるコンテナーを具体的に記述しようとしており、それに基づいてメソッドのオンとオフを切り替える必要があります。)
回避策として、これを試してみました...これは正しく機能しているようです。
#include <type_traits>
using namespace std;
template <typename T>
struct FooPointerBase {
void valid_if_pointer(T) const { }
};
template <typename T>
struct FooNonPointerBase {
void valid_if_not_pointer(T) const { }
};
template <typename T>
struct Foo : public conditional<
is_pointer<T>::value,
FooPointerBase<T>,
FooNonPointerBase<T> >::type {
};
int main(int argc, char * argv[])
{
int someInt = 1020;
#if DEMONSTRATE_ERROR_CASES
Foo<int*>().valid_if_not_pointer(&someInt);
Foo<int>().valid_if_pointer(304);
#else
Foo<int*>().valid_if_pointer(&someInt);
Foo<int>().valid_if_not_pointer(304);
#endif
return 0;
}
しかし、これが壊れていない場合(そうですか?)、特性の型をスニッフィングすることに基づいて、テンプレート化されたクラスでメソッドをオンおよびオフにする方法について、適切な一般的な方法論に従っていないことは確かです。より良い解決策はありますか?