I think this trait does what you want. It detects operator()
with any kind of signature even if it's overloaded and also if it's templatized:
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);
};
The principle is based on Member Detector idiom. As it is, it will fail to compile if you pass it a non-class type, but that shouldn't be hard to fix, I just left it out for brevity. You can also extend it to report true for functions.
Of course it doesn't give you any info about the signature(s) of operator()
whatsoever, but I believe that's not what you asked for, right?
EDIT for Klaim:
It's simple enough to make it work (return false
) with non-class types. If you rename the above class to is_callable_impl
, you can write this, for example:
template<typename T>
struct is_callable
: std::conditional<
std::is_class<T>::value,
is_callable_impl<T>,
std::false_type
>::type
{ };
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…