2

is_polymorphic_functor次の結果を得るためにメタ関数を実装しようとしています。

//non-polymorphic functor
template<typename T> struct X { void operator()(T); };

//polymorphic functor 
struct Y { template<typename T> void operator()(T); };

std::cout << is_polymorphic_functor<X<int>>::value << std::endl; //false
std::cout << is_polymorphic_functor<Y>::value << std::endl; //true

それはほんの一例です。理想的には、任意の数のパラメーターに対して機能する必要がありますoperator()(T...)。2 つのテスト ケースで失敗する @Andrei Tita のソリューションをテストするために使用したテスト ケースをさらにいくつか示します。

そして、私はこれを試しました:

template<typename F>
struct is_polymorphic_functor
{
  private:
     typedef struct { char x[1]; }  yes;
     typedef struct { char x[10]; } no;

     static yes check(...);

     template<typename T >
     static no check(T*, char (*) [sizeof(functor_traits<T>)] = 0 );            
  public:
     static const bool value = sizeof(check(static_cast<F*>(0))) == sizeof(yes);
};

の次の実装を利用しようとしますfunctor_traits:

//functor traits
template <typename T>
struct functor_traits : functor_traits<decltype(&T::operator())>{};

template <typename C, typename R, typename... A>
struct functor_traits<R(C::*)(A...) const> : functor_traits<R(C::*)(A...)>{};

template <typename C, typename R, typename... A>
struct functor_traits<R(C::*)(A...)>
{
   static const size_t arity = sizeof...(A) };

   typedef R result_type;

   template <size_t i>
   struct arg
   {
      typedef typename std::tuple_element<i, std::tuple<A...>>::type type;
   };
};

これにより、多相ファンクターに対して次のエラーが発生します。

error: decltype cannot resolve address of overloaded function

この問題を修正しis_polymorphic_functorて期待どおりに動作させるにはどうすればよいですか?

4

3 に答える 3

5

これは私のために働く:

template<typename T>
struct is_polymorphic_functor
{
private:
    //test if type U has operator()(V)
    template<typename U, typename V>
    static auto ftest(U *u, V* v) -> decltype((*u)(*v), char(0));
    static std::array<char, 2> ftest(...);

    struct private_type { };

public:
    static const bool value = sizeof(ftest((T*)nullptr, (private_type*)nullptr)) == 1;
};
于 2013-02-16T17:07:31.513 に答える
2

非ポリモーフィック ファンクタにオーバーロードされた がないと仮定すると、次のようになりoperator()ます。

template<typename T>
class is_polymorphic_functor {
  template <typename F, typename = decltype(&F::operator())>
  static constexpr bool get(int) { return false; }
  template <typename>
  static constexpr bool get(...) { return true; }

public:
  static constexpr bool value = get<T>(0);
};
于 2013-02-16T17:51:06.113 に答える
2
template<template<typename>class arbitrary>
struct pathological {
  template<typename T>
  typename std::enable_if< arbitrary<T>::value >::type operator(T) const {}
};

上記のファンクターは、真である T が 1 つだけ存在する場合、非多態的arbitrary<T>::valueです。

および おそらくで true であり、 if (任意の計算が 1 を返す)でのみ true であるtemplate<T>ファンクターを作成することは難しくありません。intdoubledouble

したがって、妥協is_polymorphicはこの宇宙の範囲を超えています。

上記が気に入らない場合 (明らかに だけではなくint、他の型が単純にオーバーロードを見つけられないため)、次のようにすることもできます。

template<template<typename>class arbitrary>
struct pathological2 {
  void operator()(int) const {}
  template<typename T>
  typename std::enable_if< arbitrary<T>::value >::type operator(T) const {}
};

ここで、2 番目の「オーバーロード」がテストされ、それが取得されるような T がない場合、すべての単一の型に対して最初のオーバーロードが発生します。

于 2013-02-16T18:23:45.357 に答える