如何实现is_polymmorphic_functor

How to implement is_polymorphic_functor?

本文关键字:is polymmorphic functor 实现 何实现      更新时间:2023-10-16

我正在尝试实现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...)。以下是我用来测试@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);
};

其试图利用CCD_ 3的以下实现:

//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按预期工作?

这对我有效:

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;
};

给定非多态函子没有重载的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);
};
template<template<typename>class arbitrary>
struct pathological {
  template<typename T>
  typename std::enable_if< arbitrary<T>::value >::type operator(T) const {}
};

上述函子是非多态的,当恰好有一个T使得arbitrary<T>::value为真时。

不难创建一个template<T>函子,该函子在int上为真,可能在double上也为真,并且只有在(任意计算返回1)时才在double上为真。

因此,毫不妥协的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 {}
};

其中测试第二个"过载",如果没有T,则每个类型都会发生第一个过载。