找出C对象是否可调用

是否可以写出类型特征,例如is_callable< T>它告诉对象是否定义了operator()?
如果调用运算符的参数事先已知,则很容易,但在一般情况下则不然.
当且仅当至少有一个重载调用运算符被定义时,我希望特征返回true.

This question是相关的并且有一个很好的答案,但它不适用于所有类型(仅适用于int-convertible类型).此外,std :: is_function有效,但仅适用于正确的C函数,而不适用于仿函数.我正在寻找更通用的解决方案.

解决方法:

我认为这个特性可以满足您的需求.它会检测operator()是否有任何类型的签名,即使它已经过载也是如果它被模板化了:

template<typename T>
struct is_callable {
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 const bool value = sizeof(test<Derived>(0)) == sizeof(yes);
};

原理是基于Member Detector idiom.实际上,如果你传递一个非类型的类型它将无法编译,但这不应该很难解决,我只是为了简洁而把它留下来.您还可以将其扩展为报告函数的true.

当然它并没有给你任何关于operator()签名的信息,但我相信这不是你要求的,对吧?

编辑Klaim

使用非类类型使其工作(返回false)非常简单.如果将上面的类重命名为is_callable_impl,则可以编写此代码,例如:

template<typename T>
struct is_callable
    : std::conditional<
        std::is_class<T>::value,
        is_callable_impl<T>,
        std::false_type
    >::type
{ };
上一篇:PHP特征 – 定义通用常量


下一篇:s3c2440裸机编程-时钟编程(一、2440时钟体系介绍)