/*============================================================================= Copyright (c) 2012 Paul Fultz II sfinae_error.cpp 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 #include template struct is_callable {}; template struct is_callable { typedef char yes; typedef long no; template struct selector {}; template static yes check( selector()(std::declval()...) )> * ); template static no check(...); static const bool value = sizeof(check(0)) == sizeof(yes); typedef std::integral_constant type; }; #define RETURN(...) -> decltype(__VA_ARGS__) { return __VA_ARGS__; } template struct sfinae_error { template struct result { typedef void type; }; template struct result::value>::type> { typedef decltype(F()(std::declval()...)) type; }; template typename result::type operator()(T &&... x) { return F()(std::forward(x)...); } }; struct S0_sfinae { template auto operator()(T t) const RETURN( t + 1 ) }; typedef sfinae_error S0; struct S1 { template auto operator()(T t) const RETURN( S0()(t) ) }; struct S2 { template auto operator()(T t) const RETURN( S1()(t) ) }; struct foo {}; int main() { int i = S2()(42); printf("%i\n", i); S2()(foo()); }