
No, I'm thinking of using SFINAE generalized for expressions (note that this requires a compiler which supports the feature, such as GCC 4.4+), that is to say to put the expressions to check for directly in the signature of the overload, be it with sizeof or decltype.
For example, to check a variant of the Callable2<F, T1, T2> concept,
template<int> struct dummy {}; template<typename T> T& make();
template<typename F, typename T1, typename T2> char callable2_impl(dummy<sizeof( typename F::result_type( make<F>()( make<T1>(), make<T2>() ) ) , 0)>*);
template<typename F, typename T1, typename T2> char (&callable2_impl(...))[2];
template<typename F, typename T1, typename T2> struct Callable2 : mpl::bool_<sizeof(callable2_impl<F, T1, T2>(0)) == 1> { };
That seems overly complicated. Why not... template <typename...> failed call(...); template <typename F, typename... Args> auto call(F&& f, Args... args) -> decltype(f(args...)); template <typename F, typename... Args> struct is_callable : not<is_same<decltype(call<F, Args...>(F(), Args()...)), failed>::type> { }; I'm waving my hands a bit since F() and Args() require everything to be default constructible, but you can get around that with some clever metaprogramming machinery and fake accessor functions. It's worth pointing out that the this decltype trick works for pretty much any possible query. Unfortunately, it fails (compilation) if f(args...) is private, but hey... It works for most functions and functors, and that's not bad. Caveat: you probably need an SVN build of GCC to actually make that work without internal compiler errors :) Andrew Sutton andrew.n.sutton@gmail.com