特定のクラス T に特定の型 Type を持つ特定の名前のメンバーがあるかどうかをコンパイル時に検出できるクラスを作成する方法を知っています。
#include <type_traits>
template <typename T, typename Type, bool = std::is_class<T>::value>
struct has_member_foo
{
private:
template <Type T::*> struct helper;
template <typename U>
static std::false_type test(...);
template <typename U>
static std::true_type test(helper<&U::foo> *);
typedef decltype(test<T>(nullptr)) testresult;
public:
static const bool value = testresult::value;
};
template <typename T, typename Type>
struct has_member_foo<T, Type, false> : std::false_type { };
struct Has_Foo
{
int foo;
};
struct Has_No_Foo
{
int bar;
};
void test()
{
static_assert(has_member_foo<Has_Foo, int>::value == true, ":(");
static_assert(has_member_foo<Has_No_Foo, int>::value == false, ":(");
static_assert(has_member_foo<int, int>::value == false, ":(");
}
ほとんどの場合、これらの特性を使用したい場合、このメンバーが特定の型に変換可能であるか、整数型であるかなどを気にするため、メンバー変数の正確な型を述べる必要があるのは好きではありません。正確なタイプについて。特定の名前のメンバー変数の存在と型を検出できるようにしたいと考えています。私はこのようなものを書くことができるようにしたいと思います:
static_assert(has_member_foo<T>::value && std::is_integral<typename has_member_foo<T>::type>::value,
"The type has to have an integral member with name foo");
コンストラクト &T::foo が合法であることがわかっている場合、次のような方法でメンバーのタイプを取得できます
template <typename T, typename U>
T get_member_type(T U::*);
typedef decltype(get_member_type(&T::foo)) the_member_type;
しかし、主にヘルパー構造体がメンバーへのポインターの署名を知る必要があるため、SFINAE で正しい結果を得る 2 つのメソッドの組み合わせを生成することはできません。最終的なコードは、引数として名前を持つプリプロセッサ マクロになるため、どのソリューションでもプリプロセッサを使用できます。