web-dev-qa-db-ja.com

関数のシグネチャを正確に一致させるテンプレートメタプログラミング

テンプレートのメタプログラミングを使用すると、型のプロパティを照会できます。たとえば、次の例では、特定の型に、引数として別の型を取り込むメンバー関数「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;
}
_
3
user3882729

あなたはほとんどそこにいた。テストを変更して、fooのアドレスを取得し、結果のメンバーへのポインターの型をそれ自体にstatic_castingしてテストしました。

#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でコンパイルされます。独自に記述する必要があります。)

0
jrok

Std :: is_sameを使用してfoos引数の正確な型と一致させることができます。最初に、比較する構造体で型を定義する必要があります。

もっと良い方法があるかもしれませんが、私は手放せません。

0
Moshe Rabaev
#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));

[〜#〜]デモ[〜#〜]

0
Piotr Skotnicki