#include <tuple>
#include <type_traits>
#include <functional>
// functor
template < class Func, class ... Args >
class is_callable
{
using yes = char ( & ) [ 2 ] ;
using no = char ( & ) [ 1 ] ;
template < class F>
static yes check( decltype( std:: declval < F& > ( ) ( std:: declval < Args> ( ) ...) ) * ) ;
template < class F>
static no check( ...) ;
public :
enum { value = ( sizeof ( check< Func> ( nullptr) ) == sizeof ( yes) ) } ;
} ;
// member function
template < typename Class, typename MemFunc, class ... Args >
class is_callable_member_function
{
using yes = char ( & ) [ 2 ] ;
using no = char ( & ) [ 1 ] ;
template < class C, class MF>
static yes check( decltype( ( std:: declval < C> ( ) .* std:: declval < MF> ( ) ) ( std:: declval < Args> ( ) ...) ) * ) ;
template < class C, class MF>
static no check( ...) ;
public :
enum { value = ( sizeof ( check< Class, MemFunc> ( nullptr) ) == sizeof ( yes) ) } ;
} ;
//////////////////////////////////
template < typename Func, typename ... Args >
void assert_is_callable( Func&& , Args&& ...)
{
static_assert( is_callable< Func, Args...> :: value ,
"the provided type is not callable with the supplied arguments" ) ;
}
template < typename Class, typename MemFunc, typename ... Args >
void assert_is_callable( Class* , MemFunc, Args&& ...)
{
static_assert( is_callable_member_function< Class, MemFunc, Args...> :: value ,
"the provided type is not callable with the supplied arguments" ) ;
}
//////////////////////////////////
struct Foo
{
void func( int , double , char )
{
}
} ;
void func( int , double , char )
{
}
int main( )
{
// member function
Foo f;
assert_is_callable( & f, & Foo:: func , 1 , 2.3 , 'c' ) ;
// lambda
auto lambda = [ ] ( int , double , char ) { } ;
assert_is_callable( lambda, 1 , 2.3 , 'c' ) ;
// free function
assert_is_callable( func, 1 , 2.3 , 'c' ) ; // selects the member_function version
return 0 ;
}
I2luY2x1ZGUgPHR1cGxlPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CiNpbmNsdWRlIDxmdW5jdGlvbmFsPgoKLy8gZnVuY3RvcgoKdGVtcGxhdGU8Y2xhc3MgRnVuYywgY2xhc3MuLi4gQXJncz4KY2xhc3MgaXNfY2FsbGFibGUKewogICAgdXNpbmcgeWVzID0gY2hhcigmKVsyXTsKICAgIHVzaW5nIG5vICA9IGNoYXIoJilbMV07CgogICAgdGVtcGxhdGU8Y2xhc3MgRj4KICAgIHN0YXRpYyB5ZXMgY2hlY2soZGVjbHR5cGUoc3RkOjpkZWNsdmFsPEYmPigpKHN0ZDo6ZGVjbHZhbDxBcmdzPigpLi4uKSkqKTsKCiAgICB0ZW1wbGF0ZTxjbGFzcyBGPgogICAgc3RhdGljIG5vIGNoZWNrKC4uLik7CnB1YmxpYzoKICAgIGVudW0geyB2YWx1ZSA9IChzaXplb2YoY2hlY2s8RnVuYz4obnVsbHB0cikpID09IHNpemVvZih5ZXMpKSB9Owp9OwoKLy8gbWVtYmVyIGZ1bmN0aW9uCgp0ZW1wbGF0ZTx0eXBlbmFtZSBDbGFzcywgdHlwZW5hbWUgTWVtRnVuYywgY2xhc3MuLi4gQXJncz4KY2xhc3MgaXNfY2FsbGFibGVfbWVtYmVyX2Z1bmN0aW9uCnsKICAgIHVzaW5nIHllcyA9IGNoYXIoJilbMl07CiAgICB1c2luZyBubyAgPSBjaGFyKCYpWzFdOwoKICAgIHRlbXBsYXRlPGNsYXNzIEMsIGNsYXNzIE1GPgogICAgc3RhdGljIHllcyBjaGVjayhkZWNsdHlwZSgoc3RkOjpkZWNsdmFsPEM+KCkuKnN0ZDo6ZGVjbHZhbDxNRj4oKSkoc3RkOjpkZWNsdmFsPEFyZ3M+KCkuLi4pKSopOwoKICAgIHRlbXBsYXRlPGNsYXNzIEMsIGNsYXNzIE1GPgogICAgc3RhdGljIG5vIGNoZWNrKC4uLik7CnB1YmxpYzoKICAgIGVudW0geyB2YWx1ZSA9IChzaXplb2YoY2hlY2s8Q2xhc3MsIE1lbUZ1bmM+KG51bGxwdHIpKSA9PSBzaXplb2YoeWVzKSkgfTsKfTsKCi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KCnRlbXBsYXRlPHR5cGVuYW1lIEZ1bmMsIHR5cGVuYW1lLi4uIEFyZ3M+CnZvaWQgYXNzZXJ0X2lzX2NhbGxhYmxlKEZ1bmMmJiwgQXJncyYmLi4uKQp7CiAgICBzdGF0aWNfYXNzZXJ0KGlzX2NhbGxhYmxlPEZ1bmMsIEFyZ3MuLi4+Ojp2YWx1ZSwKICAgICAgICAgICAgInRoZSBwcm92aWRlZCB0eXBlIGlzIG5vdCBjYWxsYWJsZSB3aXRoIHRoZSBzdXBwbGllZCBhcmd1bWVudHMiKTsKfQoKdGVtcGxhdGU8dHlwZW5hbWUgQ2xhc3MsIHR5cGVuYW1lIE1lbUZ1bmMsIHR5cGVuYW1lLi4uIEFyZ3M+CnZvaWQgYXNzZXJ0X2lzX2NhbGxhYmxlKENsYXNzKiwgTWVtRnVuYywgQXJncyYmLi4uKQp7CiAgICBzdGF0aWNfYXNzZXJ0KGlzX2NhbGxhYmxlX21lbWJlcl9mdW5jdGlvbjxDbGFzcywgTWVtRnVuYywgQXJncy4uLj46OnZhbHVlLAogICAgICAgICAgICAidGhlIHByb3ZpZGVkIHR5cGUgaXMgbm90IGNhbGxhYmxlIHdpdGggdGhlIHN1cHBsaWVkIGFyZ3VtZW50cyIpOwp9CgovLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCgpzdHJ1Y3QgRm9vCnsKICAgIHZvaWQgZnVuYyhpbnQsIGRvdWJsZSwgY2hhcikKICAgIHsKICAgIH0KfTsKCnZvaWQgZnVuYyhpbnQsIGRvdWJsZSwgY2hhcikKewp9CgppbnQgbWFpbigpCnsKICAgIC8vIG1lbWJlciBmdW5jdGlvbgogICAgRm9vIGY7CiAgICBhc3NlcnRfaXNfY2FsbGFibGUoJmYsICZGb286OmZ1bmMsIDEsIDIuMywgJ2MnKTsKCiAgICAvLyBsYW1iZGEKICAgIGF1dG8gbGFtYmRhID0gW10oaW50LCBkb3VibGUsIGNoYXIpIHsgfTsKICAgIGFzc2VydF9pc19jYWxsYWJsZShsYW1iZGEsIDEsIDIuMywgJ2MnKTsKCiAgICAvLyBmcmVlIGZ1bmN0aW9uCiAgICBhc3NlcnRfaXNfY2FsbGFibGUoZnVuYywgMSwgMi4zLCAnYycpOyAvLyBzZWxlY3RzIHRoZSBtZW1iZXJfZnVuY3Rpb24gdmVyc2lvbgoKICAgIHJldHVybiAwOwp9Cg==
compilation info
prog.cpp: In instantiation of 'void assert_is_callable(Class*, MemFunc, Args&& ...) [with Class = void(int, double, char); MemFunc = int; Args = {double, char}]':
prog.cpp:79:41: required from here
prog.cpp:51:5: error: static assertion failed: the provided type is not callable with the supplied arguments
static_assert(is_callable_member_function<Class, MemFunc, Args...>::value,
^
stdout