Embrace variadic templates
authorTimePath <andrew.hardaker1995@gmail.com>
Sun, 31 Dec 2017 05:58:54 +0000 (16:58 +1100)
committerTimePath <andrew.hardaker1995@gmail.com>
Sun, 31 Dec 2017 05:58:54 +0000 (16:58 +1100)
libs/generic/callback.h
libs/generic/functional.h
libs/signal/isignal.h
libs/signal/signal.h
libs/stringio.h
radiant/csg.cpp
radiant/dialog.h
radiant/renderstate.cpp
radiant/selection.cpp
radiant/texwindow.cpp

index 2ce007f..ef74e0c 100644 (file)
@@ -89,104 +89,6 @@ static const Type* apply( void* p ){
 }
 };
 
-template<typename Caller>
-class BindFirstOpaque
-{
-typedef typename Caller::first_argument_type FirstBound;
-FirstBound firstBound;
-public:
-typedef typename Caller::result_type result_type;
-explicit BindFirstOpaque( FirstBound firstBound ) : firstBound( firstBound ){
-}
-result_type operator()() const {
-       return Caller::call( firstBound );
-}
-FirstBound getBound() const {
-       return firstBound;
-}
-static result_type thunk( void* environment ){
-       return Caller::call( ConvertFromOpaque<FirstBound>::apply( environment ) );
-}
-void* getEnvironment() const {
-       return convertToOpaque( firstBound );
-}
-};
-
-template<typename Caller>
-class BindFirstOpaque1
-{
-typedef typename Caller::first_argument_type FirstBound;
-FirstBound firstBound;
-public:
-typedef typename Caller::second_argument_type first_argument_type;
-typedef typename Caller::result_type result_type;
-explicit BindFirstOpaque1( FirstBound firstBound ) : firstBound( firstBound ){
-}
-result_type operator()( first_argument_type a1 ) const {
-       return Caller::call( firstBound, a1 );
-}
-FirstBound getBound() const {
-       return firstBound;
-}
-static result_type thunk( void* environment, first_argument_type a1 ){
-       return Caller::call( ConvertFromOpaque<FirstBound>::apply( environment ), a1 );
-}
-void* getEnvironment() const {
-       return convertToOpaque( firstBound );
-}
-};
-
-template<typename Caller>
-class BindFirstOpaque2
-{
-typedef typename Caller::first_argument_type FirstBound;
-FirstBound firstBound;
-public:
-typedef typename Caller::second_argument_type first_argument_type;
-typedef typename Caller::third_argument_type second_argument_type;
-typedef typename Caller::result_type result_type;
-explicit BindFirstOpaque2( FirstBound firstBound ) : firstBound( firstBound ){
-}
-result_type operator()( first_argument_type a1, second_argument_type a2 ) const {
-       return Caller::call( firstBound, a1, a2 );
-}
-FirstBound getBound() const {
-       return firstBound;
-}
-static result_type thunk( void* environment, first_argument_type a1, second_argument_type a2 ){
-       return Caller::call( ConvertFromOpaque<FirstBound>::apply( environment ), a1, a2 );
-}
-void* getEnvironment() const {
-       return convertToOpaque( firstBound );
-}
-};
-
-template<typename Caller>
-class BindFirstOpaque3
-{
-typedef typename Caller::first_argument_type FirstBound;
-FirstBound firstBound;
-public:
-typedef typename Caller::second_argument_type first_argument_type;
-typedef typename Caller::third_argument_type second_argument_type;
-typedef typename Caller::fourth_argument_type third_argument_type;
-typedef typename Caller::result_type result_type;
-explicit BindFirstOpaque3( FirstBound firstBound ) : firstBound( firstBound ){
-}
-result_type operator()( first_argument_type a1, second_argument_type a2, third_argument_type a3 ) const {
-       return Caller::call( firstBound, a1, a2, a3 );
-}
-FirstBound getBound() const {
-       return firstBound;
-}
-static result_type thunk( void* environment, first_argument_type a1, second_argument_type a2, third_argument_type a3 ){
-       return Caller::call( ConvertFromOpaque<FirstBound>::apply( environment ), a1, a2, a3 );
-}
-void* getEnvironment() const {
-       return convertToOpaque( firstBound );
-}
-};
-
 template<typename Thunk_>
 class CallbackBase
 {
@@ -218,38 +120,79 @@ inline bool operator<( const CallbackBase<Thunk>& self, const CallbackBase<Thunk
                   ( !( other.getEnvironment() < self.getEnvironment() ) && self.getThunk() < other.getThunk() );
 }
 
+template<class Caller, class F>
+class BindFirstOpaqueN;
+
+template<class Caller, class R, class FirstBound, class... Ts>
+class BindFirstOpaqueN<Caller, R(FirstBound, Ts...)> {
+       FirstBound firstBound;
+public:
+       explicit BindFirstOpaqueN(FirstBound firstBound) : firstBound(firstBound) {
+       }
+
+       R operator()(Ts... args) const {
+               return Caller::call(firstBound, args...);
+       }
+
+       FirstBound getBound() const {
+               return firstBound;
+       }
+
+       static R thunk(void *environment, Ts... args) {
+               return Caller::call(ConvertFromOpaque<FirstBound>::apply(environment), args...);
+       }
+
+       void *getEnvironment() const {
+               return convertToOpaque(firstBound);
+       }
+};
+
+template<class Caller>
+using BindFirstOpaque = BindFirstOpaqueN<Caller, typename Caller::func>;
+
+template<class F>
+class CallbackN;
+
+template<class R, class... Ts>
+class CallbackN<R(Ts...)> : public CallbackBase<R(*)(void *, Ts...)> {
+       using Base = CallbackBase<R (*)(void *, Ts...)>;
+
+       static R nullThunk(void *, Ts...) {
+       }
+
+public:
+       using func = R(Ts...);
+
+       CallbackN() : Base(0, nullThunk) {
+       }
+
+       template<typename Caller>
+       CallbackN(const BindFirstOpaque<Caller> &caller) : Base(caller.getEnvironment(), BindFirstOpaque<Caller>::thunk) {
+       }
+
+       CallbackN(void *environment, typename Base::Thunk function) : Base(environment, function) {
+       }
+
+       R operator()(Ts... args) const {
+               return Base::getThunk()(Base::getEnvironment(), args...);
+       }
+};
 
 /// \brief Combines a void pointer with a pointer to a function which operates on a void pointer.
 ///
 /// Use with the callback constructors MemberCaller, ConstMemberCaller, ReferenceCaller, ConstReferenceCaller, PointerCaller, ConstPointerCaller and FreeCaller.
-template<typename Result>
-class Callback0 : public CallbackBase<Result ( * )( void* )>
-{
-typedef CallbackBase<Result ( * )( void* )> Base;
-static Result nullThunk( void* ){
-}
-
+template<class Result>
+class Callback0 : public CallbackN<Result()> {
 public:
-typedef Result result_type;
-
-Callback0() : Base( 0, nullThunk ){
-}
-template<typename Caller>
-Callback0( const BindFirstOpaque<Caller>& caller ) : Base( caller.getEnvironment(), BindFirstOpaque<Caller>::thunk ){
-}
-Callback0( void* environment, typename Base::Thunk function ) : Base( environment, function ){
-}
-result_type operator()() const {
-       return Base::getThunk() ( Base::getEnvironment() );
-}
+       using CallbackN<Result()>::CallbackN;
 };
 
 template<typename Caller>
-inline Callback0<typename Caller::result_type> makeCallback0( const Caller& caller, typename Caller::first_argument_type callee ){
-       return Callback0<typename Caller::result_type>( BindFirstOpaque<Caller>( callee ) );
+inline Callback0<get_result_type<Caller>> makeCallback0(const Caller &caller, get_argument<Caller, 0> callee) {
+       return Callback0<get_result_type<Caller>>(BindFirstOpaque<Caller>(callee));
 }
 template<typename Caller>
-inline Callback0<typename Caller::result_type> makeStatelessCallback0( const Caller& caller ){
+inline Callback0<get_result_type<Caller>> makeStatelessCallback0(const Caller &caller) {
        return makeCallback0( Caller0To1<Caller>(), 0 );
 }
 
@@ -260,35 +203,19 @@ typedef Callback0<void> Callback;
 /// \brief Combines a void pointer with a pointer to a function which operates on a void pointer and one other argument.
 ///
 /// Use with the callback constructors MemberCaller1, ConstMemberCaller1, ReferenceCaller1, ConstReferenceCaller1, PointerCaller1, ConstPointerCaller1 and FreeCaller1.
-template<typename FirstArgument, typename Result>
-class Callback1 : public CallbackBase<Result ( * )( void*, FirstArgument )>
-{
-typedef CallbackBase<Result ( * )( void*, FirstArgument )> Base;
-static Result nullThunk( void*, FirstArgument ){
-}
-
+template<class FirstArgument, class Result>
+class Callback1 : public CallbackN<Result(FirstArgument)> {
 public:
-typedef FirstArgument first_argument_type;
-typedef Result result_type;
-
-Callback1() : Base( 0, nullThunk ){
-}
-template<typename Caller>
-Callback1( const BindFirstOpaque1<Caller>& caller ) : Base( caller.getEnvironment(), BindFirstOpaque1<Caller>::thunk ){
-}
-Callback1( void* environment, typename Base::Thunk function ) : Base( environment, function ){
-}
-result_type operator()( FirstArgument firstArgument ) const {
-       return Base::getThunk() ( Base::getEnvironment(), firstArgument );
-}
+       using CallbackN<Result(FirstArgument)>::CallbackN;
 };
 
 template<typename Caller>
-inline Callback1<typename Caller::second_argument_type, typename Caller::result_type> makeCallback1( const Caller& caller, typename Caller::first_argument_type callee ){
-       return Callback1<typename Caller::second_argument_type, typename Caller::result_type>( BindFirstOpaque1<Caller>( callee ) );
+inline Callback1<get_argument<Caller, 1>, get_result_type<Caller>>
+makeCallback1(const Caller &caller, get_argument<Caller, 0> callee) {
+       return Callback1<get_argument<Caller, 1>, get_result_type<Caller>>(BindFirstOpaque<Caller>(callee));
 }
 template<typename Caller>
-inline Callback1<typename Caller::second_argument_type, typename Caller::result_type> makeStatelessCallback1( const Caller& caller ){
+inline Callback1<get_argument<Caller, 1>, get_result_type<Caller>> makeStatelessCallback1(const Caller &caller) {
        return makeCallback1( Caller1To2<Caller>(), 0 );
 }
 
@@ -296,47 +223,29 @@ inline Callback1<typename Caller::second_argument_type, typename Caller::result_
 /// \brief Combines a void pointer with a pointer to a function which operates on a void pointer and two other arguments.
 ///
 template<typename FirstArgument, typename SecondArgument, typename Result>
-class Callback2 : public CallbackBase<Result ( * )( void*, FirstArgument, SecondArgument )>
-{
-typedef CallbackBase<Result ( * )( void*, FirstArgument, SecondArgument )> Base;
-static Result nullThunk( void*, FirstArgument, SecondArgument ){
-}
-
+class Callback2 : public CallbackN<Result(FirstArgument, SecondArgument)> {
 public:
-typedef FirstArgument first_argument_type;
-typedef SecondArgument second_argument_type;
-typedef Result result_type;
-
-Callback2() : Base( 0, nullThunk ){
-}
-template<typename Caller>
-Callback2( const BindFirstOpaque2<Caller>& caller ) : Base( caller.getEnvironment(), BindFirstOpaque2<Caller>::thunk ){
-}
-Callback2( void* environment, typename Base::Thunk function ) : Base( environment, function ){
-}
-result_type operator()( FirstArgument firstArgument, SecondArgument secondArgument ) const {
-       return Base::getThunk() ( Base::getEnvironment(), firstArgument, secondArgument );
-}
+       using CallbackN<Result(FirstArgument, SecondArgument)>::CallbackN;
 };
 
 template<typename Caller>
 inline Callback2<
-       typename Caller::second_argument_type,
-       typename Caller::third_argument_type,
-       typename Caller::result_type
-       > makeCallback2( const Caller& caller, typename Caller::first_argument_type callee ){
+               get_argument<Caller, 1>,
+               get_argument<Caller, 2>,
+               get_result_type<Caller>
+> makeCallback2(const Caller &caller, get_argument<Caller, 0> callee) {
        return Callback2<
-                          typename Caller::second_argument_type,
-                          typename Caller::third_argument_type,
-                          typename Caller::result_type
-                          >( BindFirstOpaque2<Caller>( callee ) );
+                       get_argument<Caller, 1>,
+                       get_argument<Caller, 2>,
+                       get_result_type<Caller>
+       >(BindFirstOpaque<Caller>(callee));
 }
 template<typename Caller>
 inline Callback2<
-       typename Caller::first_argument_type,
-       typename Caller::second_argument_type,
-       typename Caller::result_type
-       > makeStatelessCallback2( const Caller& caller ){
+               get_argument<Caller, 0>,
+               get_argument<Caller, 1>,
+               get_result_type<Caller>
+> makeStatelessCallback2(const Caller &caller) {
        return makeCallback2( Caller2To3<Caller>(), 0 );
 }
 
@@ -344,51 +253,32 @@ inline Callback2<
 /// \brief Combines a void pointer with a pointer to a function which operates on a void pointer and three other arguments.
 ///
 template<typename FirstArgument, typename SecondArgument, typename ThirdArgument, typename Result>
-class Callback3 : public CallbackBase<Result ( * )( void*, FirstArgument, SecondArgument, ThirdArgument )>
-{
-typedef CallbackBase<Result ( * )( void*, FirstArgument, SecondArgument, ThirdArgument )> Base;
-static Result nullThunk( void*, FirstArgument, SecondArgument, ThirdArgument ){
-}
-
+class Callback3 : public CallbackN<Result(FirstArgument, SecondArgument, ThirdArgument)> {
 public:
-typedef FirstArgument first_argument_type;
-typedef SecondArgument second_argument_type;
-typedef ThirdArgument third_argument_type;
-typedef Result result_type;
-
-Callback3() : Base( 0, nullThunk ){
-}
-template<typename Caller>
-Callback3( const BindFirstOpaque3<Caller>& caller ) : Base( caller.getEnvironment(), BindFirstOpaque3<Caller>::thunk ){
-}
-Callback3( void* environment, typename Base::Thunk function ) : Base( environment, function ){
-}
-result_type operator()( FirstArgument firstArgument, SecondArgument secondArgument, ThirdArgument thirdArgument ) const {
-       return Base::getThunk() ( Base::getEnvironment(), firstArgument, secondArgument, thirdArgument );
-}
+       using CallbackN<Result(FirstArgument, SecondArgument, ThirdArgument)>::CallbackN;
 };
 
 template<typename Caller>
 inline Callback3<
-       typename Caller::second_argument_type,
-       typename Caller::third_argument_type,
-       typename Caller::fourth_argument_type,
-       typename Caller::result_type
-       > makeCallback3( const Caller& caller, typename Caller::first_argument_type callee ){
+               get_argument<Caller, 1>,
+               get_argument<Caller, 2>,
+               get_argument<Caller, 3>,
+               get_result_type<Caller>
+> makeCallback3(const Caller &caller, get_argument<Caller, 0> callee) {
        return Callback3<
-                          typename Caller::second_argument_type,
-                          typename Caller::third_argument_type,
-                          typename Caller::fourth_argument_type,
-                          typename Caller::result_type
-                          >( BindFirstOpaque3<Caller>( callee ) );
+                       get_argument<Caller, 1>,
+                       get_argument<Caller, 2>,
+                       get_argument<Caller, 3>,
+                       get_result_type<Caller>
+       >(BindFirstOpaque<Caller>(callee));
 }
 template<typename Caller>
 inline Callback3<
-       typename Caller::first_argument_type,
-       typename Caller::second_argument_type,
-       typename Caller::third_argument_type,
-       typename Caller::result_type
-       > makeStatelessCallback3( const Caller& caller ){
+               get_argument<Caller, 0>,
+               get_argument<Caller, 1>,
+               get_argument<Caller, 2>,
+               get_result_type<Caller>
+> makeStatelessCallback3(const Caller &caller) {
        return makeCallback3( Caller3To4<Caller>(), 0 );
 }
 
@@ -398,141 +288,79 @@ inline Callback3<
 /// \dontinclude generic/callback.cpp
 /// \skipline MemberCaller example
 /// \until end example
-template<typename Environment, void( Environment::*member ) ( )>
-class MemberCaller : public BindFirstOpaque< Member<Environment, void, member> >
-{
-public:
-MemberCaller( Environment& environment ) : BindFirstOpaque< Member<Environment, void, member> >( environment ){
-}
-};
+template<class Environment, void(Environment::*member)()>
+using MemberCaller = BindFirstOpaque<Member<Environment, void, member>>;
 
 /// \brief Forms a Callback from a const Environment reference and a const Environment member-function.
 ///
 /// \dontinclude generic/callback.cpp
 /// \skipline MemberCaller example
 /// \until end example
-template<typename Environment, void( Environment::*member ) ( ) const>
-class ConstMemberCaller : public BindFirstOpaque< ConstMember<Environment, void, member> >
-{
-public:
-ConstMemberCaller( const Environment& environment ) : BindFirstOpaque< ConstMember<Environment, void, member> >( environment ){
-}
-};
+template<class Environment, void(Environment::*member)() const>
+using ConstMemberCaller = BindFirstOpaque<ConstMember<Environment, void, member>>;
 
 /// \brief Forms a Callback from a non-const Environment reference and a const Environment member-function which takes one argument.
-template<typename Environment, typename FirstArgument, void( Environment::*member ) (FirstArgument)>
-class MemberCaller1 : public BindFirstOpaque1< Member1<Environment, FirstArgument, void, member> >
-{
-public:
-MemberCaller1( Environment& environment ) : BindFirstOpaque1< Member1<Environment, FirstArgument, void, member> >( environment ){
-}
-};
+template<class Environment, class FirstArgument, void(Environment::*member)(FirstArgument)>
+using MemberCaller1 = BindFirstOpaque<Member1<Environment, FirstArgument, void, member>>;
 
 /// \brief Forms a Callback from a const Environment reference and a const Environment member-function which takes one argument.
-template<typename Environment, typename FirstArgument, void( Environment::*member ) (FirstArgument) const>
-class ConstMemberCaller1 : public BindFirstOpaque1< ConstMember1<Environment, FirstArgument, void, member> >
-{
-public:
-ConstMemberCaller1( const Environment& environment ) : BindFirstOpaque1< ConstMember1<Environment, FirstArgument, void, member> >( environment ){
-}
-};
+template<class Environment, class FirstArgument, void(Environment::*member)(FirstArgument) const>
+using ConstMemberCaller1 = BindFirstOpaque<ConstMember1<Environment, FirstArgument, void, member>>;
 
 /// \brief Forms a Callback from a non-const Environment reference and a free function which operates on a non-const Environment reference.
 ///
 /// \dontinclude generic/callback.cpp
 /// \skipline ReferenceCaller example
 /// \until end example
-template<typename Environment, void( *func ) (Environment&)>
-class ReferenceCaller : public BindFirstOpaque< Function1<Environment&, void, func> >
-{
-public:
-ReferenceCaller( Environment& environment ) : BindFirstOpaque< Function1<Environment&, void, func> >( environment ){
-}
-};
+template<class Environment, void(*func)(Environment &)>
+using ReferenceCaller = BindFirstOpaque<Function1<Environment &, void, func>>;
 
 /// \brief Forms a Callback from a const Environment reference and a free function which operates on a const Environment reference.
 ///
 /// \dontinclude generic/callback.cpp
 /// \skipline ReferenceCaller example
 /// \until end example
-template<typename Environment, void( *func ) (const Environment&)>
-class ConstReferenceCaller : public BindFirstOpaque< Function1<const Environment&, void, func> >
-{
-public:
-ConstReferenceCaller( const Environment& environment ) : BindFirstOpaque< Function1<const Environment&, void, func> >( environment ){
-}
-};
+template<class Environment, void(*func)(const Environment &)>
+using ConstReferenceCaller = BindFirstOpaque<Function1<const Environment &, void, func>>;
 
 /// \brief Forms a Callback from a non-const Environment reference and a free function which operates on a non-const Environment reference and one other argument.
-template<typename Environment, typename FirstArgument, void( *func ) ( Environment&, FirstArgument )>
-class ReferenceCaller1 : public BindFirstOpaque1< Function2<Environment&, FirstArgument, void, func> >
-{
-public:
-ReferenceCaller1( Environment& environment ) : BindFirstOpaque1< Function2<Environment&, FirstArgument, void, func> >( environment ){
-}
-};
+template<class Environment, class FirstArgument, void(*func)(Environment &, FirstArgument)>
+using ReferenceCaller1 = BindFirstOpaque<Function2<Environment &, FirstArgument, void, func>>;
 
 /// \brief Forms a Callback from a const Environment reference and a free function which operates on a const Environment reference and one other argument.
-template<typename Environment, typename FirstArgument, void( *func ) ( const Environment&, FirstArgument )>
-class ConstReferenceCaller1 : public BindFirstOpaque1< Function2<const Environment&, FirstArgument, void, func> >
-{
-public:
-ConstReferenceCaller1( const Environment& environment ) : BindFirstOpaque1< Function2<const Environment&, FirstArgument, void, func> >( environment ){
-}
-};
+template<class Environment, class FirstArgument, void(*func)(const Environment &, FirstArgument)>
+using ConstReferenceCaller1 = BindFirstOpaque<Function2<const Environment &, FirstArgument, void, func>>;
 
 /// \brief Forms a Callback from a non-const Environment pointer and a free function which operates on a non-const Environment pointer.
-template<typename Environment, void( *func ) (Environment*)>
-class PointerCaller : public BindFirstOpaque< Function1<Environment*, void, func> >
-{
-public:
-PointerCaller( Environment* environment ) : BindFirstOpaque< Function1<Environment*, void, func> >( environment ){
-}
-};
+template<class Environment, void(*func)(Environment *)>
+using PointerCaller = BindFirstOpaque<Function1<Environment *, void, func>>;
 
 /// \brief Forms a Callback from a const Environment pointer and a free function which operates on a const Environment pointer.
-template<typename Environment, void( *func ) (const Environment*)>
-class ConstPointerCaller : public BindFirstOpaque< Function1<const Environment*, void, func> >
-{
-public:
-ConstPointerCaller( const Environment* environment ) : BindFirstOpaque< Function1<const Environment*, void, func> >( environment ){
-}
-};
+template<class Environment, void(*func)(const Environment *)>
+using ConstPointerCaller = BindFirstOpaque<Function1<const Environment *, void, func>>;
 
 /// \brief Forms a Callback from a non-const Environment pointer and a free function which operates on a non-const Environment pointer and one other argument.
-template<typename Environment, typename FirstArgument, void( *func ) ( Environment*, FirstArgument )>
-class PointerCaller1 : public BindFirstOpaque1< Function2<Environment*, FirstArgument, void, func> >
-{
-public:
-PointerCaller1( Environment* environment ) : BindFirstOpaque1< Function2<Environment*, FirstArgument, void, func> >( environment ){
-}
-};
+template<class Environment, class FirstArgument, void(*func)(Environment *, FirstArgument)>
+using PointerCaller1 = BindFirstOpaque<Function2<Environment *, FirstArgument, void, func>>;
 
 /// \brief Forms a Callback from a const Environment pointer and a free function which operates on a const Environment pointer and one other argument.
-template<typename Environment, typename FirstArgument, void( *func ) ( const Environment*, FirstArgument )>
-class ConstPointerCaller1 : public BindFirstOpaque1< Function2<const Environment*, FirstArgument, void, func> >
-{
-public:
-ConstPointerCaller1( const Environment* environment ) : BindFirstOpaque1< Function2<const Environment*, FirstArgument, void, func> >( environment ){
-}
-};
+template<class Environment, class FirstArgument, void(*func)(const Environment *, FirstArgument)>
+using ConstPointerCaller1 = BindFirstOpaque<Function2<const Environment *, FirstArgument, void, func>>;
 
 /// \brief Forms a Callback from a free function which takes no arguments.
-template<void( *func ) ( )>
-class FreeCaller : public BindFirstOpaque< Caller0To1< Function0<void, func> > >
-{
+template<void(*func)()>
+class FreeCaller : public BindFirstOpaque<Caller0To1<Function0<void, func>>> {
 public:
-FreeCaller() : BindFirstOpaque< Caller0To1< Function0<void, func> > >( 0 ){
-}
+       FreeCaller() : BindFirstOpaque<Caller0To1<Function0<void, func>>>(0) {
+       }
 };
 
 /// \brief Forms a Callback from a free function which takes a single argument.
-template<typename FirstArgument, void( *func ) (FirstArgument)>
-class FreeCaller1 : public BindFirstOpaque1< Caller1To2< Function1<FirstArgument, void, func> > >
-{
+template<class FirstArgument, void(*func)(FirstArgument)>
+class FreeCaller1 : public BindFirstOpaque<Caller1To2<Function1<FirstArgument, void, func>>> {
 public:
-FreeCaller1() : BindFirstOpaque1< Caller1To2< Function1<FirstArgument, void, func> > >( 0 ){
-}
+       FreeCaller1() : BindFirstOpaque<Caller1To2<Function1<FirstArgument, void, func>>>(0) {
+       }
 };
 
 
@@ -556,8 +384,8 @@ inline Callback makeCallback( const Functor& functor ){
 ///
 /// \param Functor Must define \c first_argument_type and \c operator()(first_argument_type).
 template<typename Functor>
-inline Callback1<typename Functor::first_argument_type> makeCallback1( Functor& functor ){
-       typedef typename Functor::first_argument_type FirstArgument;
+inline Callback1<get_argument<Functor, 0>> makeCallback1(Functor &functor) {
+       typedef get_argument<Functor, 0> FirstArgument;
        return Callback1<FirstArgument>( MemberCaller1<Functor, FirstArgument, &Functor::operator()>( functor ) );
 }
 
@@ -565,8 +393,8 @@ inline Callback1<typename Functor::first_argument_type> makeCallback1( Functor&
 ///
 /// \param Functor Must define \c first_argument_type and const \c operator()(first_argument_type).
 template<typename Functor>
-inline Callback1<typename Functor::first_argument_type> makeCallback1( const Functor& functor ){
-       typedef typename Functor::first_argument_type FirstArgument;
+inline Callback1<get_argument<Functor, 0>> makeCallback1(const Functor &functor) {
+       typedef get_argument<Functor, 0> FirstArgument;
        return Callback1<FirstArgument>( ConstMemberCaller1<Functor, FirstArgument, &Functor::operator()>( functor ) );
 }
 
index 940d4e7..7d76a8b 100644 (file)
-
 #if !defined( INCLUDED_FUNCTIONAL_H )
 #define INCLUDED_FUNCTIONAL_H
 
-template<typename Object, typename R, R( Object::*member ) ( )>
-class Member
-{
-public:
-typedef Object& first_argument_type;
-typedef R result_type;
-static result_type call( first_argument_type object ){
-       return ( object.*member )();
-}
-};
+#include <tuple>
 
-template<typename Object, typename R, R( Object::*member ) ( ) const>
-class ConstMember
-{
-public:
-typedef const Object& first_argument_type;
-typedef R result_type;
-static result_type call( first_argument_type object ){
-       return ( object.*member )();
-}
-};
+namespace detail {
+    template<class F>
+    struct Fn;
 
-template<typename Object, typename A1, typename R, R( Object::*member ) (A1)>
-class Member1
-{
-public:
-typedef Object& first_argument_type;
-typedef A1 second_argument_type;
-typedef R result_type;
-static result_type call( first_argument_type object, second_argument_type a1 ){
-       return ( object.*member )( a1 );
-}
-};
+    template<class R, class... Ts>
+    struct Fn<R(Ts...)> {
+        using result_type = R;
 
-template<typename Object, typename A1, typename R, R( Object::*member ) (A1) const>
-class ConstMember1
-{
-public:
-typedef const Object& first_argument_type;
-typedef A1 second_argument_type;
-typedef R result_type;
-static result_type call( first_argument_type object, second_argument_type a1 ){
-       return ( object.*member )( a1 );
+        template<int N>
+        using get = typename std::tuple_element<N, std::tuple<Ts...>>::type;
+    };
 }
-};
 
-template<typename Object, typename A2, typename A3, typename R, R( Object::*member ) ( A2, A3 )>
-class Member2
-{
-public:
-typedef Object& first_argument_type;
-typedef A2 second_argument_type;
-typedef A3 third_argument_type;
-typedef R result_type;
-static result_type call( first_argument_type object, second_argument_type a2, third_argument_type a3 ){
-       return ( object.*member )( a2, a3 );
-}
-};
+template<class Caller>
+using get_result_type = typename detail::Fn<typename Caller::func>::result_type;
 
-template<typename Object, typename A2, typename A3, typename R, R( Object::*member ) ( A2, A3 ) const>
-class ConstMember2
-{
-public:
-typedef const Object& first_argument_type;
-typedef A2 second_argument_type;
-typedef A3 third_argument_type;
-typedef R result_type;
-static result_type call( first_argument_type object, second_argument_type a2, third_argument_type a3 ){
-       return ( object.*member )( a2, a3 );
-}
-};
+template<class Caller, int N>
+using get_argument = typename detail::Fn<typename Caller::func>::template get<N>;
 
-template<typename Object, typename A2, typename A3, typename A4, typename R, R( Object::*member ) ( A2, A3, A4 )>
-class Member3
-{
-public:
-typedef Object& first_argument_type;
-typedef A2 second_argument_type;
-typedef A3 third_argument_type;
-typedef A4 fourth_argument_type;
-typedef R result_type;
-static result_type call( first_argument_type object, second_argument_type a2, third_argument_type a3, fourth_argument_type a4 ){
-       return ( object.*member )( a2, a3, a4 );
-}
-};
+template<class Object, class F>
+class MemberN;
 
-template<typename Object, typename A2, typename A3, typename A4, typename R, R( Object::*member ) ( A2, A3, A4 ) const>
-class ConstMember3
-{
+template<class Object, class R, class... Ts>
+class MemberN<Object, R(Ts...)> {
 public:
-typedef const Object& first_argument_type;
-typedef A2 second_argument_type;
-typedef A3 third_argument_type;
-typedef A4 fourth_argument_type;
-typedef R result_type;
-static result_type call( first_argument_type object, second_argument_type a2, third_argument_type a3, fourth_argument_type a4 ){
-       return ( object.*member )( a2, a3, a4 );
-}
-};
+    template<R(Object::*f)(Ts...)>
+    class instance {
+    public:
+        using func = R(Object &, Ts...);
 
-template<typename R, R( *func ) ( )>
-class Function0
-{
-public:
-typedef R result_type;
-static result_type call(){
-       return (func)( );
-}
+        static R call(Object &object, Ts... args) {
+            return (object.*f)(args...);
+        }
+    };
 };
 
-template<typename A1, typename R, R( *func ) (A1)>
-class Function1
-{
-public:
-typedef A1 first_argument_type;
-typedef R result_type;
-static result_type call( first_argument_type a1 ){
-       return (func)( a1 );
-}
-};
+template<class Object, class F>
+class ConstMemberN;
 
-template<typename A1, typename A2, typename R, R( *func ) ( A1, A2 )>
-class Function2
-{
+template<class Object, class R, class... Ts>
+class ConstMemberN<Object, R(Ts...)> {
 public:
-typedef A1 first_argument_type;
-typedef A2 second_argument_type;
-typedef R result_type;
-static result_type call( first_argument_type a1, second_argument_type a2 ){
-       return (func)( a1, a2 );
-}
-};
+    template<R(Object::*f)(Ts...) const>
+    class instance {
+    public:
+        using func = R(const Object &, Ts...);
 
-template<typename A1, typename A2, typename A3, typename R, R( *func ) ( A1, A2, A3 )>
-class Function3
-{
-public:
-typedef A1 first_argument_type;
-typedef A2 second_argument_type;
-typedef A3 third_argument_type;
-typedef R result_type;
-static result_type call( first_argument_type a1, second_argument_type a2, third_argument_type a3 ){
-       return (func)( a1, a2, a3 );
-}
+        static R call(const Object &object, Ts... args) {
+            return (object.*f)(args...);
+        }
+    };
 };
 
-template<typename A1, typename A2, typename A3, typename A4, typename R, R( *func ) ( A1, A2, A3, A4 )>
-class Function4
-{
-public:
-typedef A1 first_argument_type;
-typedef A2 second_argument_type;
-typedef A3 third_argument_type;
-typedef A4 fourth_argument_type;
-typedef R result_type;
-static result_type call( first_argument_type a1, second_argument_type a2, third_argument_type a3, fourth_argument_type a4 ){
-       return (func)( a1, a2, a3, a4 );
-}
-};
+template<class F>
+class FunctionN;
 
-template<typename Caller, typename FirstArgument = void*>
-class Caller0To1
-{
+template<class R, class... Ts>
+class FunctionN<R(Ts...)> {
 public:
-typedef FirstArgument first_argument_type;
-typedef typename Caller::result_type result_type;
-static result_type call( first_argument_type ){
-       return Caller::call();
-}
-};
+    template<R(*f)(Ts...)>
+    class instance {
+    public:
+        using func = R(Ts...);
 
-template<typename Caller, typename FirstArgument = void*>
-class Caller1To2
-{
-public:
-typedef FirstArgument first_argument_type;
-typedef typename Caller::first_argument_type second_argument_type;
-typedef typename Caller::result_type result_type;
-static result_type call( first_argument_type, second_argument_type a2 ){
-       return Caller::call( a2 );
-}
+        static R call(Ts... args) {
+            return (f)(args...);
+        }
+    };
 };
 
-template<typename Caller, typename FirstArgument = void*>
-class Caller2To3
-{
-public:
-typedef FirstArgument first_argument_type;
-typedef typename Caller::first_argument_type second_argument_type;
-typedef typename Caller::second_argument_type third_argument_type;
-typedef typename Caller::result_type result_type;
-static result_type call( first_argument_type, second_argument_type a2, third_argument_type a3 ){
-       return Caller::call( a2, a3 );
-}
-};
+template<class Caller, class F>
+class CallerShiftFirst;
 
-template<typename Caller, typename FirstArgument = void*>
-class Caller3To4
-{
+template<class Caller, class R, class FirstArgument, class... Ts>
+class CallerShiftFirst<Caller, R(FirstArgument, Ts...)> {
 public:
-typedef FirstArgument first_argument_type;
-typedef typename Caller::first_argument_type second_argument_type;
-typedef typename Caller::second_argument_type third_argument_type;
-typedef typename Caller::third_argument_type fourth_argument_type;
-typedef typename Caller::result_type result_type;
-static result_type call( first_argument_type, second_argument_type a2, third_argument_type a3, fourth_argument_type a4 ){
-       return Caller::call( a2, a3, a4 );
-}
-};
+    using func = R(FirstArgument, Ts...);
 
-template<typename Functor>
-class FunctorInvoke
-{
-public:
-typedef typename Functor::result_type result_type;
-inline result_type operator()( Functor functor ){
-       return functor();
-}
+    static R call(FirstArgument, Ts... args) {
+        return Caller::call(args...);
+    }
 };
 
-template<typename Functor>
-class Functor1Invoke
-{
-typename Functor::first_argument_type a1;
-public:
-typedef typename Functor::first_argument_type first_argument_type;
-typedef typename Functor::result_type result_type;
-Functor1Invoke( first_argument_type a1 ) : a1( a1 ){
-}
-inline result_type operator()( Functor functor ){
-       return functor( a1 );
-}
-};
+template<class Functor, class F>
+class FunctorNInvoke;
 
-template<typename Functor>
-class Functor2Invoke
-{
-typename Functor::first_argument_type a1;
-typename Functor::second_argument_type a2;
-public:
-typedef typename Functor::first_argument_type first_argument_type;
-typedef typename Functor::second_argument_type second_argument_type;
-typedef typename Functor::result_type result_type;
-Functor2Invoke( first_argument_type a1, second_argument_type a2 )
-       : a1( a1 ), a2( a2 ){
-}
-inline result_type operator()( Functor functor ){
-       return functor( a1, a2 );
-}
-};
+namespace detail {
+    template<int ...>
+    struct seq {
+    };
 
-template<typename Functor>
-class Functor3Invoke
-{
-typename Functor::first_argument_type a1;
-typename Functor::second_argument_type a2;
-typename Functor::third_argument_type a3;
-public:
-typedef typename Functor::first_argument_type first_argument_type;
-typedef typename Functor::second_argument_type second_argument_type;
-typedef typename Functor::third_argument_type third_argument_type;
-typedef typename Functor::result_type result_type;
-Functor3Invoke( first_argument_type a1, second_argument_type a2, third_argument_type a3 )
-       : a1( a1 ), a2( a2 ), a3( a3 ){
-}
-inline result_type operator()( Functor functor ){
-       return functor( a1, a2, a3 );
+    template<int N, int... S>
+    struct gens : gens<N - 1, N - 1, S...> {
+    };
+
+    template<int... S>
+    struct gens<0, S...> {
+        using type = seq<S...>;
+    };
+
+    template<int N>
+    using seq_new = typename gens<N>::type;
 }
-};
 
-template<typename Other, typename True, typename False, typename Type>
-class TypeEqual
-{
-public:
-typedef False type;
-};
-template<typename Other, typename True, typename False>
-class TypeEqual<Other, True, False, Other>
-{
+template<class Functor, class R, class... Ts>
+class FunctorNInvoke<Functor, R(Ts...)> {
+    std::tuple<Ts...> args;
+
+    template<class T>
+    struct caller;
+
+    template<int ...I>
+    struct caller<detail::seq<I...>> {
+        static inline R call(FunctorNInvoke<Functor, R(Ts...)> *self, Functor functor) {
+            (void) self;
+            return functor(std::get<I>(self->args)...);
+        }
+    };
+
 public:
-typedef True type;
+    FunctorNInvoke(Ts... args) : args(args...) {
+    }
+
+    inline R operator()(Functor functor) {
+        return caller<detail::seq_new<sizeof...(Ts)>>::call(this, functor);
+    }
 };
 
+template<class Functor>
+using FunctorInvoke = FunctorNInvoke<Functor, typename Functor::func>;
+
+template<class Object, class R, R(Object::*member)()>
+using Member = typename MemberN<Object, R()>::template instance<member>;
+
+template<class Object, class R, R(Object::*member)() const>
+using ConstMember = typename ConstMemberN<Object, R()>::template instance<member>;
+
+template<class Object, class A1, class R, R(Object::*member)(A1)>
+using Member1 = typename MemberN<Object, R(A1)>::template instance<member>;
+
+template<class Object, class A1, class R, R(Object::*member)(A1) const>
+using ConstMember1 = typename ConstMemberN<Object, R(A1)>::template instance<member>;
+
+template<class Object, class A1, class A2, class R, R(Object::*member)(A1, A2)>
+using Member2 = typename MemberN<Object, R(A1, A2)>::template instance<member>;
+
+template<class Object, class A1, class A2, class R, R(Object::*member)(A1, A2) const>
+using ConstMember2 = typename ConstMemberN<Object, R(A1, A2)>::template instance<member>;
+
+template<class Object, class A1, class A2, class A3, class R, R(Object::*member)(A1, A2, A3)>
+using Member3 = typename MemberN<Object, R(A1, A2, A3)>::template instance<member>;
+
+template<class Object, class A1, class A2, class A3, class R, R(Object::*member)(A1, A2, A3) const>
+using ConstMember3 = typename ConstMemberN<Object, R(A1, A2, A3)>::template instance<member>;
+
+template<class R, R(*func)()>
+using Function0 = typename FunctionN<R()>::template instance<func>;
+
+template<class A1, class R, R(*func)(A1)>
+using Function1 = typename FunctionN<R(A1)>::template instance<func>;
+
+template<class A1, class A2, class R, R(*func)(A1, A2)>
+using Function2 = typename FunctionN<R(A1, A2)>::template instance<func>;
+
+template<class A1, class A2, class A3, class R, R(*func)(A1, A2, A3)>
+using Function3 = typename FunctionN<R(A1, A2, A3)>::template instance<func>;
+
+template<class A1, class A2, class A3, class A4, class R, R(*func)(A1, A2, A3, A4)>
+using Function4 = typename FunctionN<R(A1, A2, A3, A4)>::template instance<func>;
+
+template<class Caller, class FirstArgument = void *>
+using Caller0To1 = CallerShiftFirst<Caller, get_result_type<Caller>(
+        FirstArgument
+)>;
+
+template<class Caller, class FirstArgument = void *>
+using Caller1To2 = CallerShiftFirst<Caller, get_result_type<Caller>(
+        FirstArgument,
+        get_argument<Caller, 0>
+)>;
+
+template<class Caller, class FirstArgument = void *>
+using Caller2To3 = CallerShiftFirst<Caller, get_result_type<Caller>(
+        FirstArgument,
+        get_argument<Caller, 0>,
+        get_argument<Caller, 1>
+)>;
+
+template<class Caller, class FirstArgument = void *>
+using Caller3To4 = CallerShiftFirst<Caller, get_result_type<Caller>(
+        FirstArgument,
+        get_argument<Caller, 0>,
+        get_argument<Caller, 1>,
+        get_argument<Caller, 2>
+)>;
 
 #endif
index b634219..c447d71 100644 (file)
@@ -22,72 +22,63 @@ bool operator!=( SignalHandlerResult other ) const {
 const SignalHandlerResult SIGNAL_CONTINUE_EMISSION = SignalHandlerResult( false );
 const SignalHandlerResult SIGNAL_STOP_EMISSION = SignalHandlerResult( true );
 
-template<typename Caller>
-class SignalHandlerCaller1
-{
+template<class Caller, class F>
+class SignalHandlerCallerN;
+
+template<class Caller, class R, class... Ts>
+class SignalHandlerCallerN<Caller, R(Ts...)> {
 public:
-typedef typename Caller::first_argument_type first_argument_type;
-typedef SignalHandlerResult result_type;
-static result_type call( first_argument_type a1 ){
-       Caller::call( a1 );
-       return SIGNAL_CONTINUE_EMISSION;
-}
+    using func = SignalHandlerResult(Ts...);
+
+    static SignalHandlerResult call(Ts... args) {
+        Caller::call(args...);
+        return SIGNAL_CONTINUE_EMISSION;
+    }
 };
 
+template<class Caller>
+using SignalHandlerCaller = SignalHandlerCallerN<Caller, typename Caller::func>;
+
+template<class Caller>
+using SignalHandlerCaller1 = SignalHandlerCaller<Caller>;
+
+template<class Caller>
+using SignalHandlerCaller2 = SignalHandlerCaller<Caller>;
+
 template<typename Caller>
-class SignalHandlerCaller2
-{
-public:
-typedef typename Caller::first_argument_type first_argument_type;
-typedef typename Caller::second_argument_type second_argument_type;
-typedef SignalHandlerResult result_type;
-static result_type call( first_argument_type a1, second_argument_type a2 ){
-       Caller::call( a1, a2 );
-       return SIGNAL_CONTINUE_EMISSION;
-}
-};
+using SignalHandlerCaller3 = SignalHandlerCaller<Caller>;
 
 template<typename Caller>
-class SignalHandlerCaller3
-{
+using SignalHandlerCaller4 = SignalHandlerCaller<Caller>;
+
+template<typename Other, typename True, typename False, typename Type>
+class TypeEqual {
 public:
-typedef typename Caller::first_argument_type first_argument_type;
-typedef typename Caller::second_argument_type second_argument_type;
-typedef typename Caller::third_argument_type third_argument_type;
-typedef SignalHandlerResult result_type;
-static result_type call( first_argument_type a1, second_argument_type a2, third_argument_type a3 ){
-       Caller::call( a1, a2, a3 );
-       return SIGNAL_CONTINUE_EMISSION;
-}
+    using type = False;
 };
 
-template<typename Caller>
-class SignalHandlerCaller4
-{
+template<typename Other, typename True, typename False>
+class TypeEqual<Other, True, False, Other> {
 public:
-typedef typename Caller::first_argument_type first_argument_type;
-typedef typename Caller::second_argument_type second_argument_type;
-typedef typename Caller::third_argument_type third_argument_type;
-typedef typename Caller::fourth_argument_type fourth_argument_type;
-typedef SignalHandlerResult result_type;
-static result_type call( first_argument_type a1, second_argument_type a2, third_argument_type a3, fourth_argument_type a4 ){
-       Caller::call( a1, a2, a3, a4 );
-       return SIGNAL_CONTINUE_EMISSION;
-}
+    using type = True;
 };
 
-class SignalHandler : public Callback0<SignalHandlerResult>
-{
+template<class CB, template<class T> class Wrapper>
+class SignalHandlerN : public CB {
 public:
-template<typename Caller>
-SignalHandler( const BindFirstOpaque<Caller>& caller )
-       : Callback0<SignalHandlerResult>( BindFirstOpaque<typename TypeEqual<
-                                                                                                                 SignalHandlerResult,
-                                                                                                                 Caller,
-                                                                                                                 SignalHandlerCaller1<Caller>,
-                                                                                                                 typename Caller::result_type
-                                                                                                                 >::type>( caller.getBound() ) ){
-}
+    template<typename Caller>
+    SignalHandlerN(const BindFirstOpaque<Caller> &caller)
+            : CB(BindFirstOpaque<typename TypeEqual<
+            SignalHandlerResult,
+            Caller,
+            Wrapper<Caller>,
+            get_result_type<Caller>
+    >::type>(caller.getBound())) {
+    }
+};
+
+class SignalHandler : public SignalHandlerN<Callback0<SignalHandlerResult>, SignalHandlerCaller1> {
+    using SignalHandlerN<Callback0<SignalHandlerResult>, SignalHandlerCaller1>::SignalHandlerN;
 };
 
 template<typename Caller>
@@ -95,111 +86,81 @@ inline SignalHandler makeSignalHandler( const BindFirstOpaque<Caller>& caller ){
        return SignalHandler( caller );
 }
 template<typename Caller>
-inline SignalHandler makeSignalHandler( const Caller& caller, typename Caller::first_argument_type callee ){
+inline SignalHandler makeSignalHandler(const Caller &caller, get_argument<Caller, 0> callee) {
        return SignalHandler( BindFirstOpaque<Caller>( callee ) );
 }
 
-
 template<typename FirstArgument>
-class SignalHandler1 : public Callback1<FirstArgument, SignalHandlerResult>
-{
-public:
-template<typename Caller>
-SignalHandler1( const BindFirstOpaque1<Caller>& caller )
-       : Callback1<FirstArgument, SignalHandlerResult>( BindFirstOpaque1<typename TypeEqual<
-                                                                                                                                                 SignalHandlerResult,
-                                                                                                                                                 Caller,
-                                                                                                                                                 SignalHandlerCaller2<Caller>,
-                                                                                                                                                 typename Caller::result_type
-                                                                                                                                                 >::type>( caller.getBound() ) ){
-}
+class SignalHandler1 : public SignalHandlerN<Callback1<FirstArgument, SignalHandlerResult>, SignalHandlerCaller2> {
+    using SignalHandlerN<Callback1<FirstArgument, SignalHandlerResult>, SignalHandlerCaller2>::SignalHandlerN;
 };
 
 template<typename Caller>
-inline SignalHandler1<typename Caller::second_argument_type> makeSignalHandler1( const BindFirstOpaque1<Caller>& caller ){
-       return SignalHandler1<typename Caller::second_argument_type>( caller );
+inline SignalHandler1<get_argument<Caller, 1>> makeSignalHandler1(const BindFirstOpaque<Caller> &caller) {
+    return SignalHandler1<get_argument<Caller, 1>>(caller);
 }
 template<typename Caller>
-inline SignalHandler1<typename Caller::second_argument_type> makeSignalHandler1( const Caller& caller, typename Caller::first_argument_type callee ){
-       return SignalHandler1<typename Caller::second_argument_type>( BindFirstOpaque1<Caller>( callee ) );
+inline SignalHandler1<get_argument<Caller, 1>>
+makeSignalHandler1(const Caller &caller, get_argument<Caller, 0> callee) {
+    return SignalHandler1<get_argument<Caller, 1>>(BindFirstOpaque<Caller>(callee));
 }
 
-
 template<typename FirstArgument, typename SecondArgument>
-class SignalHandler2 : public Callback2<FirstArgument, SecondArgument, SignalHandlerResult>
-{
-public:
-template<typename Caller>
-SignalHandler2( const BindFirstOpaque2<Caller>& caller )
-       : Callback2<FirstArgument, SecondArgument, SignalHandlerResult>( BindFirstOpaque2<typename TypeEqual<
-                                                                                                                                                                                 SignalHandlerResult,
-                                                                                                                                                                                 Caller,
-                                                                                                                                                                                 SignalHandlerCaller3<Caller>,
-                                                                                                                                                                                 typename Caller::result_type
-                                                                                                                                                                                 >::type>( caller.getBound() ) ){
-}
+class SignalHandler2
+        : public SignalHandlerN<Callback2<FirstArgument, SecondArgument, SignalHandlerResult>, SignalHandlerCaller3> {
+    using SignalHandlerN<Callback2<FirstArgument, SecondArgument, SignalHandlerResult>, SignalHandlerCaller3>::SignalHandlerN;
 };
 
 template<typename Caller>
 inline SignalHandler2<
-       typename Caller::second_argument_type,
-       typename Caller::third_argument_type
-       > makeSignalHandler2( const BindFirstOpaque2<Caller>& caller ){
+        get_argument<Caller, 1>,
+        get_argument<Caller, 2>
+> makeSignalHandler2(const BindFirstOpaque<Caller> &caller) {
        return SignalHandler2<
-                          typename Caller::second_argument_type,
-                          typename Caller::third_argument_type
+            get_argument<Caller, 1>,
+            get_argument<Caller, 2>
                           >( caller );
 }
 template<typename Caller>
 inline SignalHandler2<
-       typename Caller::second_argument_type,
-       typename Caller::third_argument_type
-       > makeSignalHandler2( const Caller& caller, typename Caller::first_argument_type callee ){
+        get_argument<Caller, 1>,
+        get_argument<Caller, 2>
+> makeSignalHandler2(const Caller &caller, get_argument<Caller, 0> callee) {
        return SignalHandler2<
-                          typename Caller::second_argument_type,
-                          typename Caller::third_argument_type
-                          >( BindFirstOpaque2<Caller>( callee ) );
+            get_argument<Caller, 1>,
+            get_argument<Caller, 2>
+    >(BindFirstOpaque<Caller>(callee));
 }
 
-
 template<typename FirstArgument, typename SecondArgument, typename ThirdArgument>
-class SignalHandler3 : public Callback3<FirstArgument, SecondArgument, ThirdArgument, SignalHandlerResult>
-{
-public:
-template<typename Caller>
-SignalHandler3( const BindFirstOpaque3<Caller>& caller )
-       : Callback3<FirstArgument, SecondArgument, ThirdArgument, SignalHandlerResult>( BindFirstOpaque3<typename TypeEqual<
-                                                                                                                                                                                                                SignalHandlerResult,
-                                                                                                                                                                                                                Caller,
-                                                                                                                                                                                                                SignalHandlerCaller4<Caller>,
-                                                                                                                                                                                                                typename Caller::result_type
-                                                                                                                                                                                                                >::type>( caller.getBound() ) ){
-}
+class SignalHandler3
+        : public SignalHandlerN<Callback3<FirstArgument, SecondArgument, ThirdArgument, SignalHandlerResult>, SignalHandlerCaller4> {
+    using SignalHandlerN<Callback3<FirstArgument, SecondArgument, ThirdArgument, SignalHandlerResult>, SignalHandlerCaller4>::SignalHandlerN;
 };
 
 template<typename Caller>
 inline SignalHandler3<
-       typename Caller::second_argument_type,
-       typename Caller::third_argument_type,
-       typename Caller::fourth_argument_type
-       > makeSignalHandler3( const BindFirstOpaque3<Caller>& caller ){
+        get_argument<Caller, 1>,
+        get_argument<Caller, 2>,
+        get_argument<Caller, 3>
+> makeSignalHandler3(const BindFirstOpaque<Caller> &caller) {
        return SignalHandler3<
-                          typename Caller::second_argument_type,
-                          typename Caller::third_argument_type,
-                          typename Caller::fourth_argument_type
+            get_argument<Caller, 1>,
+            get_argument<Caller, 2>,
+            get_argument<Caller, 3>
                           >( caller );
 }
 template<typename Caller>
 inline SignalHandler3<
-       typename Caller::second_argument_type,
-       typename Caller::third_argument_type,
-       typename Caller::fourth_argument_type
-       > makeSignalHandler3( const Caller& caller, typename Caller::first_argument_type callee ){
+        get_argument<Caller, 1>,
+        get_argument<Caller, 2>,
+        get_argument<Caller, 3>
+> makeSignalHandler3(const Caller &caller, get_argument<Caller, 0> callee) {
        return SignalHandler3<
-                          typename Caller::second_argument_type,
-                          typename Caller::third_argument_type,
-                          typename Caller::fourth_argument_type
-                          >( BindFirstOpaque3<Caller>( callee ) );
+            get_argument<Caller, 1>,
+            get_argument<Caller, 2>,
+            get_argument<Caller, 3>
+    >(BindFirstOpaque<Caller>(callee));
 }
 
 #endif
index f435f02..3d4c039 100644 (file)
@@ -315,7 +315,7 @@ class Signal1 : public SignalBase< SignalHandler1<FirstArgument> >
 typedef SignalBase< SignalHandler1<FirstArgument> > Base;
 public:
 void operator()( FirstArgument a1 ) const {
-       invokeSignalHandlers( Base::begin(), Base::end(), Functor1Invoke<typename Base::handler_type>( a1 ) );
+       invokeSignalHandlers( Base::begin(), Base::end(), FunctorInvoke<typename Base::handler_type>( a1 ) );
 }
 };
 
@@ -325,7 +325,7 @@ class Signal2 : public SignalBase< SignalHandler2<FirstArgument, SecondArgument>
 typedef SignalBase< SignalHandler2<FirstArgument, SecondArgument> > Base;
 public:
 void operator()( FirstArgument a1, SecondArgument a2 ) const {
-       invokeSignalHandlers( Base::begin(), Base::end(), Functor2Invoke<typename Base::handler_type>( a1, a2 ) );
+       invokeSignalHandlers( Base::begin(), Base::end(), FunctorInvoke<typename Base::handler_type>( a1, a2 ) );
 }
 };
 
@@ -335,7 +335,7 @@ class Signal3 : public SignalBase< SignalHandler3<FirstArgument, SecondArgument,
 typedef SignalBase< SignalHandler3<FirstArgument, SecondArgument, ThirdArgument> > Base;
 public:
 void operator()( FirstArgument a1, SecondArgument a2, ThirdArgument a3 ) const {
-       invokeSignalHandlers( Base::begin(), Base::end(), Functor3Invoke<typename Base::handler_type>( a1, a2, a3 ) );
+       invokeSignalHandlers( Base::begin(), Base::end(), FunctorInvoke<typename Base::handler_type>( a1, a2, a3 ) );
 }
 };
 
index ac68025..ef80859 100644 (file)
@@ -397,12 +397,12 @@ typedef ConstReferenceCaller1<StringImportCallback, bool, Bool_toString> BoolToS
 
 template<typename Caller>
 inline StringImportCallback makeBoolStringImportCallback( const Caller& caller ){
-       return StringImportCallback( caller.getEnvironment(), ImportConvert1<StringImportCallback::first_argument_type, Caller, BoolFromString>::thunk );
+       return StringImportCallback( caller.getEnvironment(), ImportConvert1<get_argument<StringImportCallback, 0>, Caller, BoolFromString>::thunk );
 }
 
 template<typename Caller>
 inline StringExportCallback makeBoolStringExportCallback( const Caller& caller ){
-       return StringExportCallback( caller.getEnvironment(), ImportConvert1<StringExportCallback::first_argument_type, Caller, BoolToString>::thunk );
+       return StringExportCallback( caller.getEnvironment(), ImportConvert1<get_argument<StringExportCallback, 0>, Caller, BoolToString>::thunk );
 }
 
 
@@ -427,12 +427,12 @@ typedef ConstReferenceCaller1<StringImportCallback, int, Int_toString> IntToStri
 
 template<typename Caller>
 inline StringImportCallback makeIntStringImportCallback( const Caller& caller ){
-       return StringImportCallback( caller.getEnvironment(), ImportConvert1<StringImportCallback::first_argument_type, Caller, IntFromString>::thunk );
+       return StringImportCallback( caller.getEnvironment(), ImportConvert1<get_argument<StringImportCallback, 0>, Caller, IntFromString>::thunk );
 }
 
 template<typename Caller>
 inline StringExportCallback makeIntStringExportCallback( const Caller& caller ){
-       return StringExportCallback( caller.getEnvironment(), ImportConvert1<StringExportCallback::first_argument_type, Caller, IntToString>::thunk );
+       return StringExportCallback( caller.getEnvironment(), ImportConvert1<get_argument<StringExportCallback, 0>, Caller, IntToString>::thunk );
 }
 
 
@@ -458,12 +458,12 @@ typedef ConstReferenceCaller1<StringImportCallback, std::size_t, Size_toString>
 
 template<typename Caller>
 inline StringImportCallback makeSizeStringImportCallback( const Caller& caller ){
-       return StringImportCallback( caller.getEnvironment(), ImportConvert1<StringImportCallback::first_argument_type, Caller, SizeFromString>::thunk );
+       return StringImportCallback( caller.getEnvironment(), ImportConvert1<get_argument<StringImportCallback, 0>, Caller, SizeFromString>::thunk );
 }
 
 template<typename Caller>
 inline StringExportCallback makeSizeStringExportCallback( const Caller& caller ){
-       return StringExportCallback( caller.getEnvironment(), ImportConvert1<StringExportCallback::first_argument_type, Caller, SizeToString>::thunk );
+       return StringExportCallback( caller.getEnvironment(), ImportConvert1<get_argument<StringExportCallback, 0>, Caller, SizeToString>::thunk );
 }
 
 #endif
index 5676401..2538359 100644 (file)
@@ -166,11 +166,9 @@ class Dereference
 {
 const Functor& functor;
 public:
-typedef typename RemoveReference<typename Functor::first_argument_type>::type* first_argument_type;
-typedef typename Functor::result_type result_type;
 Dereference( const Functor& functor ) : functor( functor ){
 }
-result_type operator()( first_argument_type firstArgument ) const {
+get_result_type<Functor> operator()( typename RemoveReference<get_argument<Functor, 0>>::type *firstArgument ) const {
        return functor( *firstArgument );
 }
 };
@@ -192,15 +190,13 @@ Face* Brush_findIf( const Brush& brush, const Predicate& predicate ){
 template<typename Caller>
 class BindArguments1
 {
-typedef typename Caller::second_argument_type FirstBound;
+typedef get_argument<Caller, 1> FirstBound;
 FirstBound firstBound;
 public:
-typedef typename Caller::result_type result_type;
-typedef typename Caller::first_argument_type first_argument_type;
 BindArguments1( FirstBound firstBound )
        : firstBound( firstBound ){
 }
-result_type operator()( first_argument_type firstArgument ) const {
+get_result_type<Caller> operator()( get_argument<Caller, 0> firstArgument ) const {
        return Caller::call( firstArgument, firstBound );
 }
 };
@@ -208,17 +204,15 @@ result_type operator()( first_argument_type firstArgument ) const {
 template<typename Caller>
 class BindArguments2
 {
-typedef typename Caller::second_argument_type FirstBound;
-typedef typename Caller::third_argument_type SecondBound;
+typedef get_argument<Caller, 1> FirstBound;
+typedef get_argument<Caller, 2> SecondBound;
 FirstBound firstBound;
 SecondBound secondBound;
 public:
-typedef typename Caller::result_type result_type;
-typedef typename Caller::first_argument_type first_argument_type;
 BindArguments2( FirstBound firstBound, SecondBound secondBound )
        : firstBound( firstBound ), secondBound( secondBound ){
 }
-result_type operator()( first_argument_type firstArgument ) const {
+get_result_type<Caller> operator()( get_argument<Caller, 0> firstArgument ) const {
        return Caller::call( firstArgument, firstBound, secondBound );
 }
 };
index b862daa..13ff605 100644 (file)
 #include <list>
 #include <uilib/uilib.h>
 
+#include "generic/callback.h"
 #include "gtkutil/dialog.h"
 #include "generic/callback.h"
 #include "string/string.h"
 
-template<typename Environment, typename FirstArgument, void( *func ) ( Environment&, FirstArgument )>
-class ReferenceCaller1;
-
 inline void BoolImport( bool& self, bool value ){
        self = value;
 }
index 0c27491..b906f2c 100644 (file)
@@ -908,7 +908,7 @@ OpenGLStateBucket& m_bucket;
 const OpenGLRenderable& m_renderable;
 const Matrix4& m_modelview;
 public:
-typedef const RendererLight& first_argument_type;
+using func = void(const RendererLight&);
 
 OpenGLStateBucketAdd( OpenGLStateBucket& bucket, const OpenGLRenderable& renderable, const Matrix4& modelview ) :
        m_bucket( bucket ), m_renderable( renderable ), m_modelview( modelview ){
@@ -922,7 +922,7 @@ class CountLights
 {
 std::size_t m_count;
 public:
-typedef RendererLight& first_argument_type;
+using func = void(RendererLight&);
 
 CountLights() : m_count( 0 ){
 }
index e04fd91..830937e 100644 (file)
@@ -1982,7 +1982,7 @@ void TestQuadStrip( const VertexPointer& vertices, const IndexPointer& indices,
 class SelectionCounter
 {
 public:
-typedef const Selectable& first_argument_type;
+using func = void(const Selectable &);
 
 SelectionCounter( const SelectionChangeCallback& onchanged )
        : m_count( 0 ), m_onchanged( onchanged ){
index 8e2ed43..639dd49 100644 (file)
@@ -756,7 +756,7 @@ class TextureCategoryLoadShader
 const char* m_directory;
 std::size_t& m_count;
 public:
-typedef const char* first_argument_type;
+using func = void(const char *);
 
 TextureCategoryLoadShader( const char* directory, std::size_t& count )
        : m_directory( directory ), m_count( count ){