是否可以写出类型特征,例如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
{ };