テンプレートのメタプログラミングを使用すると、型のプロパティを照会できます。たとえば、次の例では、特定の型に、引数として別の型を取り込むメンバー関数「foo」があるかどうかを確認しています。
パラメータタイプがテンプレートとテンプレートに完全に一致するかどうかを確認する方法はありますか。 doubleまたはcharはfloatに変換できます(mainがtrueを2回出力するようになります)が、完全に一致するように_my_test_t
_を構造化する方法があるかどうかを確認しようとしています。つまり、main()
prints _T2 = float
_でない限りfalse。
_struct S2
{
int foo(float x)
{
return 0;
}
};
template <typename T1, typename T2>
using my_test_t = decltype(declval<T1>().foo(declval<T2>()));
template <typename T1, typename T2, typename = void>
struct is_formed : std::false_type
{
};
template <typename T1, typename T2>
struct is_formed<T1, T2, void_t<my_test_t<T1, T2>>> : std::true_type
{
};
int main()
{
cout << boolalpha << is_formed<S2, double>::value << endl;
cout << boolalpha << is_formed<S2, char>::value << endl;
}
_
あなたはほとんどそこにいた。テストを変更して、foo
のアドレスを取得し、結果のメンバーへのポインターの型をそれ自体にstatic_cast
ingしてテストしました。
#include <type_traits>
#include <iostream>
using namespace std;
struct S2
{
int foo(float x)
{
return 0;
}
};
template <typename T1, typename T2>
using my_test_t = decltype( static_cast<int(T1::*)(T2)>(&T1::foo) );
template <typename T1, typename T2, typename = void>
struct is_formed : std::false_type
{ };
template <typename T1, typename T2>
struct is_formed<T1, T2, void_t< my_test_t<T1,T2> >> : std::true_type
{ };
int main()
{
cout << boolalpha << is_formed<S2, float>::value << endl; // true
cout << boolalpha << is_formed<S2, double>::value << endl; // false
cout << boolalpha << is_formed<S2, char>::value << endl; // false
}
(C++ 14にはstd :: void_tがないため、上記のコードはC++ 17でコンパイルされます。独自に記述する必要があります。)
Std :: is_sameを使用してfoos引数の正確な型と一致させることができます。最初に、比較する構造体で型を定義する必要があります。
もっと良い方法があるかもしれませんが、私は手放せません。
#include <type_traits>
#include <utility>
template <typename C, typename P>
auto test(short) -> std::false_type;
template <typename C, typename P>
auto test(int)
-> decltype(static_cast<decltype(std::declval<C&>().foo(std::declval<P>())) (C::*)(P)>(&C::foo)
, std::true_type{});
template <typename C, typename P>
using my_test_t = decltype(test<C, P>(0));