可调用的类成员检测器习语和C++11最终版本

Callable class member detector idiom and C++11 final

本文关键字:C++11 版本 习语 检测器 调用 成员      更新时间:2023-10-16

我想检测一个类型是否是可调用的,以下内容适用于所有未标记为final:的类

template<typename T>
struct is_callable_impl {
 private:
  typedef char(&yes)[1];
  typedef char(&no)[2];
  struct fallback {
    void operator()();
  };
  struct derived
    : T, fallback {};
  template<typename U, U> struct check;
  template<typename>
  static yes test(...);
  template<typename C>
  static no test(check<void (fallback::*)(), &C::operator()>*);
 public:
   static constexpr bool value = sizeof(test<derived>(0)) == sizeof(yes);
};
template<typename T>
struct is_callable
: std::conditional<
    std::is_function<T>::value,
    std::true_type,
    typename std::conditional<
        std::is_class<T>::value,
        is_callable_impl<T>,
        std::false_type
    >::type
>::type {};

这是C++03方式的成员检测器习惯用法,但我们现在可以将SFINAE表达式与decltype一起使用。我不知道如何在类型上检测任何过载的operator()?以上使用fallback来检测T.上是否没有可用的可调用函数指针

实时演示

我会做

#define DEFINE_HAS_SIGNATURE(traitsName, funcName, signature)               
    template <typename U>                                                   
    class traitsName                                                        
    {                                                                       
    private:                                                                
        template<typename T, T> struct helper;                              
        template<typename T>                                                
        static std::uint8_t check(helper<signature, &funcName>*);           
        template<typename T> static std::uint16_t check(...);               
    public:                                                                 
        static                                                              
        constexpr bool value = sizeof(check<U>(0)) == sizeof(std::uint8_t); 
    }
DEFINE_HAS_SIGNATURE(is_callable, T::operator (), void (T::*)() const);

演示