#include <string>
#include <iostream>
#include <boost/function.hpp>
namespace detail {
template<typename T> struct IsClassType {
template<typename U> static char (& is(U *U::*) )[1];
template<typename U> static char (& is(...) )[2];
static bool const value = (sizeof is<T>(0) == 1);
};
struct Marker { };
struct Detector { };
template<typename U> struct Detected { };
template<typename U> Detected<U> operator,(Detector, U const&);
template<typename U> char (& operator,(Detected<U>, char(&)[2]) )[2];
char (& operator,(Detected<Marker>, char(&)[2]) )[1];
}
#define IS_CALLABLE(N, ARGS, TNAME) \
template<typename T, \
bool IsClassType = detail::IsClassType<T>::value> \
struct TNAME##_hasN { \
struct D1 { void N(); }; \
struct D : D1, T { }; \
\
template<typename U, U> struct ChT; \
\
template<typename U> \
static char (& has(ChT<void (D1::*)(), &U::N>*) )[1]; \
\
template<typename U> \
static char (& has(...) )[2]; \
\
static bool const value = (sizeof has<D>(0) == 2); \
}; \
\
template<typename T> struct TNAME##_hasN<T, false> \
{ static bool const value = false; }; \
\
template<typename T, bool HasIt = TNAME##_hasN<T>::value> \
struct TNAME { \
struct Fallback { detail::Marker N(...) const volatile; }; \
struct Derived : T, Fallback { \
using T::N; using Fallback::N; \
}; \
\
static bool const value = \
sizeof (detail::Detector(), \
(*(Derived*)0) ARGS, *(char(*)[2])0) \
== 2; \
}; \
\
template<typename T> struct TNAME<T, false> \
{ static bool const value = false; }
IS_CALLABLE(f, .f(""), CanCallF); // callable with .f("")
IS_CALLABLE(f, .f(true), CanCallFb); // callable with .f(true)
IS_CALLABLE(g, .g(""), CanCallG); // callable with .g("")
IS_CALLABLE(c_str, .c_str(), CanCallCStr); // callable with .c_str()
IS_CALLABLE(operator(), (true), CanCallB); // callable with (true)
struct A {
void f(std::string);
};
struct B : A { };
int main() {
std::cout << CanCallF<B>::value << std::endl
<< CanCallFb<B>::value << std::endl
<< CanCallG<B>::value << std::endl
<< CanCallCStr<const std::string>::value << std::endl
<< CanCallB< boost::function<void(bool)> >::value << std::endl
<< CanCallB< boost::function<void(bool*)> >::value << std::endl;
}