//////////////////////////////////////////////////////////////////////////////////////////////////// // main.cpp // // Copyright 2012 Eric Niebler. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include #include #define ENABLE_IF(...) \ typename std::enable_if(__VA_ARGS__)>::type *& = enabler extern void *enabler; #define RETURN(...) -> decltype(__VA_ARGS__) { return __VA_ARGS__; } //////////////////////////////////////////////////////////////////////////////////////// // sfinae_error template struct sfinae_error; template struct sfinae_error { virtual sfinae_error what() const noexcept { typedef decltype(std::declval()(std::declval()...)) type; return *this; } }; template void void_(T const &); //////////////////////////////////////////////////////////////////////////////////////// // Many thanks to Paul Fultz for the ideas behind the unsfinae function wrapper template struct is_callable : std::false_type {}; template struct is_callable< Fun(Args...) , decltype(void_(std::declval()(std::declval()...))) > : std::true_type {}; template struct try_call { template::value)> auto operator()(Args &&...args) const RETURN( Fun()(static_cast(args)...) ) template::value)> auto operator()(Args &&...) const RETURN( sfinae_error() ) }; struct S0 { template auto operator()(T t) const RETURN( t + 1 ) }; struct S1 { template auto operator()(T t) const RETURN( try_call()(t) ) }; struct S2 { template auto operator()(T t) const RETURN( try_call()(t) ) }; struct foo {}; int main() { int i = S2()(32); auto x = S2()(foo()); }