#include <iostream>
int& func()
{
static int p;
return p;
}
int first_param() { return func() = 0 ; }
int next_param() { return ++func() ; }
template < std::size_t N > struct do_call_fn ;
template <> struct do_call_fn<0>
{ template < typename FN > static int call( FN fn) { return fn() ; } };
template <> struct do_call_fn<1>
{
template < typename FN > static int call( FN fn)
{ return fn( first_param() ) ; }
};
template <> struct do_call_fn<2>
{
template < typename FN > static int call( FN fn)
{ auto a = first_param() ; return fn( a, next_param() ) ; }
};
template <> struct do_call_fn<3>
{
template < typename FN > static int call( FN fn)
{
auto a = first_param() ;
auto b = next_param() ;
return fn( a, b, next_param() ) ;
}
};
template <> struct do_call_fn<4>
{
template < typename FN > static int call( FN fn)
{
auto a = first_param() ;
auto b = next_param() ;
auto c = next_param() ;
return fn( a, b, c, next_param() ) ;
}
};
template < typename... ARGS > int call_fn( int (&fn)( ARGS... ) )
{ return do_call_fn< sizeof...(ARGS) >::call(fn) ; }
int f() { std::cout << "f()\n" ; return 0 ; }
int g(int) { std::cout << "g(int)\n" ; return 1 ; }
int h(int,int) { std::cout << "h(int,int)\n" ; return 2 ; }
int i(int,int,int) { std::cout << "i(int,int,int)\n" ; return 3 ; }
int j(int,int,int,int) { std::cout << "j(int,int,int,int)\n" ; return 3 ; }
int main()
{
call_fn(f) ;
call_fn(g) ;
call_fn(h) ;
call_fn(i) ;
call_fn(j) ;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKaW50JiBmdW5jKCkKewogICAgc3RhdGljIGludCBwOwogICAgcmV0dXJuIHA7Cn0KCmludCBmaXJzdF9wYXJhbSgpIHsgcmV0dXJuIGZ1bmMoKSA9IDAgOyB9CgppbnQgbmV4dF9wYXJhbSgpIHsgcmV0dXJuICsrZnVuYygpIDsgfQoKdGVtcGxhdGUgPCBzdGQ6OnNpemVfdCBOID4gc3RydWN0IGRvX2NhbGxfZm4gOwoKdGVtcGxhdGUgPD4gc3RydWN0IGRvX2NhbGxfZm48MD4KeyB0ZW1wbGF0ZSA8IHR5cGVuYW1lIEZOID4gc3RhdGljIGludCBjYWxsKCBGTiBmbikgeyByZXR1cm4gZm4oKSA7IH0gfTsKCnRlbXBsYXRlIDw+IHN0cnVjdCBkb19jYWxsX2ZuPDE+CnsKICAgIHRlbXBsYXRlIDwgdHlwZW5hbWUgRk4gPiBzdGF0aWMgaW50IGNhbGwoIEZOIGZuKQogICAgeyByZXR1cm4gZm4oIGZpcnN0X3BhcmFtKCkgKSA7IH0KfTsKCnRlbXBsYXRlIDw+IHN0cnVjdCBkb19jYWxsX2ZuPDI+CnsKICAgIHRlbXBsYXRlIDwgdHlwZW5hbWUgRk4gPiBzdGF0aWMgaW50IGNhbGwoIEZOIGZuKQogICAgeyBhdXRvIGEgPSBmaXJzdF9wYXJhbSgpIDsgcmV0dXJuIGZuKCBhLCBuZXh0X3BhcmFtKCkgKSA7IH0KfTsKCnRlbXBsYXRlIDw+IHN0cnVjdCBkb19jYWxsX2ZuPDM+CnsKICAgIHRlbXBsYXRlIDwgdHlwZW5hbWUgRk4gPiBzdGF0aWMgaW50IGNhbGwoIEZOIGZuKQogICAgewogICAgICAgIGF1dG8gYSA9IGZpcnN0X3BhcmFtKCkgOwogICAgICAgIGF1dG8gYiA9IG5leHRfcGFyYW0oKSA7CiAgICAgICAgcmV0dXJuIGZuKCBhLCBiLCBuZXh0X3BhcmFtKCkgKSA7CiAgICB9Cn07Cgp0ZW1wbGF0ZSA8PiBzdHJ1Y3QgZG9fY2FsbF9mbjw0Pgp7CiAgICB0ZW1wbGF0ZSA8IHR5cGVuYW1lIEZOID4gc3RhdGljIGludCBjYWxsKCBGTiBmbikKICAgIHsKICAgICAgICBhdXRvIGEgPSBmaXJzdF9wYXJhbSgpIDsKICAgICAgICBhdXRvIGIgPSBuZXh0X3BhcmFtKCkgOwogICAgICAgIGF1dG8gYyA9IG5leHRfcGFyYW0oKSA7CiAgICAgICAgcmV0dXJuIGZuKCBhLCBiLCBjLCBuZXh0X3BhcmFtKCkgKSA7CiAgICB9Cn07CnRlbXBsYXRlIDwgdHlwZW5hbWUuLi4gQVJHUyA+IGludCBjYWxsX2ZuKCBpbnQgKCZmbikoIEFSR1MuLi4gKSApCnsgcmV0dXJuIGRvX2NhbGxfZm48IHNpemVvZi4uLihBUkdTKSA+OjpjYWxsKGZuKSA7IH0KCmludCBmKCkgeyBzdGQ6OmNvdXQgPDwgImYoKVxuIiA7IHJldHVybiAwIDsgfQppbnQgZyhpbnQpIHsgc3RkOjpjb3V0IDw8ICJnKGludClcbiIgOyByZXR1cm4gMSA7IH0KaW50IGgoaW50LGludCkgeyBzdGQ6OmNvdXQgPDwgImgoaW50LGludClcbiIgOyByZXR1cm4gMiA7IH0KaW50IGkoaW50LGludCxpbnQpIHsgc3RkOjpjb3V0IDw8ICJpKGludCxpbnQsaW50KVxuIiA7IHJldHVybiAzIDsgfQppbnQgaihpbnQsaW50LGludCxpbnQpIHsgc3RkOjpjb3V0IDw8ICJqKGludCxpbnQsaW50LGludClcbiIgOyByZXR1cm4gMyA7IH0KCmludCBtYWluKCkKewogICBjYWxsX2ZuKGYpIDsKICAgY2FsbF9mbihnKSA7CiAgIGNhbGxfZm4oaCkgOwogICBjYWxsX2ZuKGkpIDsKICAgY2FsbF9mbihqKSA7Cn0K