Alternate Functor Implementation

Developers
2009-01-28
2013-04-08
  • Matthew Elkins

    Matthew Elkins - 2009-01-28

    Greetings all; I am (clearly) not a Loki developer but from time to time I do toy around with the concepts and code presented in Modern C++ Design and thought you all might be interested in an alternate implementation for generalized functors. 

    I've found that for many applications I use functors with bound parameters more than "raw" functors, and have often desired greater flexibility when doing so.  For example, I'll often want to easily bind an "arbitrary" number of parameters (as much as non-variadic templates will allow, at least) in arbitrary positions, e.g., something akin to:

    ///// BEGIN EXAMPLE /////
    // Function to be called
    void Foo(int, int, int, int) {}

    // Bind the 2nd (in a 0-based list) and 4th parameters of Foo to 5 and 17, respectively
    Functor<void, Params<int, int> > fun(&Foo, Bind<1>(5), Bind<3>(17));

    // Call is equivalent to Foo(9, 5, 100, 17)
    fun(9, 100);
    ///// END EXAMPLE /////

    I may be mistaken, but I am under the impression that Loki functors do not allow arbitrarily-positioned parameters to be bound (at least, not without writing forwarding functions), and in order to bind more than one parameter functors must be chained, which is a hassle and implies speed and storage hits.

    My alternate implementation involves the idea of packing arguments and bound parameters into two separate "lists", then unpacking them at the time of the function call.  The argument list is composed of a linear inheritance hierarchy generated via my Params (essentially the same as a Loki::Seq) containing each type (in order) of the arguments for the functor.  Each class in the hierarchy stores one argument, and the entire list (called an ArgList) is packed at the onset of the invocation, in Functor::operator()(...).  As with Loki's functors, the arglist is then passed to base class FunctorImp::operator()(ArgList) which is overridden in a derived class FunctorFinalImp.  One useful side-effect of the argument packing here is that there is no need to implement many FunctorImps or FunctorFinalImps; it is sufficient to template on the ArgList type.

    Once in FunctorFinalImp::operator()(ArgList), the argument order is resolved against a list of bound arguments, called a BinderList.  This BinderList was created when the Functor was first instantiated, and similar to the ArgList, consists of a linear hierarchy generated by Params containing each bound type.  Just as with an ArgList, each class in a BinderList hierarchy stores one bound argument; however, unlike an ArgList, each class also stores (imbedded in its type) the index for that parameter in the function call.  The index is obtained from the act of binding the parameter; for example, Bind<1>(5) means bind the int 5 at parameter 1 (again, this is 0-based).  This BinderList is stored in the FunctorFinalImp (actually, it's not quite stored there for optimization reasons, but I'm eliding optimization details for right now) and used in resolving the function call argument order.

    To resolve the argument order, the algorithm is fairly simple; for each parameter at index n, if n is one of the indices in the BinderList, use the argument stored there.  Otherwise, calculate how many indices in the BinderList are less than n.  Let x = n - #indices_in_BinderList_less_than_n, and use the xth parameter from the ArgList.  These calculations are all (of course) done at compile time, so that the post-compilation function call looks something like

    Foo(GetArgList<0>(), GetBinderList<0>(), GetArgList<1>(), GetBinderList<1>())

    in the example above.  Again, optimization details such as resolving appropriate pass-by-values into pass-by-reference-to-consts and not storing empty BinderLists are being elided, but that is the gist.  It scales nicely, as the intermediate classes can take advantage of the packed form to pass the lists around as whole units instead of needed to be explicitly coded for each number of parameters.  The packing itself is very fast, but does represent a slight slowdown relative to Loki functors in the case of no bound parameters.  I haven't run exhaustive benchmarks by any means, but I would expect my functors to be relatively faster as more and more parameters were bound due to obviating the need for chained function calls, and of course there is the space savings of not storing each functor pointer.  At any rate, the important point to me is that the performance is in the same ballpark as Loki's, since I use functors for flexibility, not speed (for which there are always raw function pointers).

    If you are interested in my implementation, you are welcome to it; I didn't post it right away because it could use some more explanation and for all I know Loki functors can in fact easily bind many parameters to arbitrary positions (if this is the case, please disabuse me of the notion!).

    In any event, thanks for listening.
    -Matt Elkins

     
    • Omer Katz

      Omer Katz - 2009-01-29

      I am not aware of such functionality.
      If you claim that when no parameters are bound it's a bit slower maybe you can specialize it to go back to the original implementation can't you?
      I'd like to see the code, even if Loki does implant such functionality yours might be better :)

       
    • Omer Katz

      Omer Katz - 2009-01-29

      Hi,
      I checked it.
      Current binding allows you to pre-set parameters:
      "Given a Functor that takes two integers,
      you want to bind one integer to some fixed value and let only the other one vary. Binding yields a
      Functor that takes only one integer, because the other one is fixed and therefore known, as illustrated in
      the following example." From Andrei's book...
      I'd like to see your implementation please :)

       
    • Matthew Elkins

      Matthew Elkins - 2009-01-30

      I don't see how to post attachments, so I guess I'll just copy in the code; of course, since it is split up into several files, this could get ugly.  I'll do one file per post to hopefully make this easier, starting with the next post.

      Some quick notes
      * My library is called 'Rice' (it's my coding staple), and it's always under development; pretty much nothing is really a finished product
      * ListMacros is a[n admittedly ugly] way of quickly generating numeric lists.  They work for 30 parameters (0-29)
      * Static is a lot like TypeTraits and TypeList put together; general compile-time helpers
      * SmartPtr.h and SmallAllocator.h are referenced in the files, but in the interest of not making this a ridiculous amount to paste I'm not including them; they are my own implementation of the same concepts in Loki, and while they vary slightly they are not really needed for comprehension.  Loki's could be directly substituted for compilation.

      I considered special-casing for speed, but it requires delaying the packing of the arguments, which (theoretically) implies a slowdown in the case of bound parameters.  This slowdown should be less than that which results from chaining function calls, but it didn't seem worthwhile at the time to write a lot of special-case code to just rebalance performance hits; I could certainly be convinced otherwise :)

      Please let me know if you have trouble compiling or following this code; it's not really "cleaned-up", so to speak.
      -Matt Elkins

       
    • Matthew Elkins

      Matthew Elkins - 2009-01-30

      #ifndef RICE_LISTMACROS_H
      #define RICE_LISTMACROS_H

      #define RICE_1_LIST0(MARK1, POSTMARK, DELIMITER) MARK1##0 POSTMARK
      #define RICE_1_LIST1(MARK1, POSTMARK, DELIMITER) RICE_1_LIST0(MARK1, POSTMARK, DELIMITER) DELIMITER MARK1##1 POSTMARK
      #define RICE_1_LIST2(MARK1, POSTMARK, DELIMITER) RICE_1_LIST1(MARK1, POSTMARK, DELIMITER) DELIMITER MARK1##2 POSTMARK
      #define RICE_1_LIST3(MARK1, POSTMARK, DELIMITER) RICE_1_LIST2(MARK1, POSTMARK, DELIMITER) DELIMITER MARK1##3 POSTMARK
      #define RICE_1_LIST4(MARK1, POSTMARK, DELIMITER) RICE_1_LIST3(MARK1, POSTMARK, DELIMITER) DELIMITER MARK1##4 POSTMARK
      #define RICE_1_LIST5(MARK1, POSTMARK, DELIMITER) RICE_1_LIST4(MARK1, POSTMARK, DELIMITER) DELIMITER MARK1##5 POSTMARK
      #define RICE_1_LIST6(MARK1, POSTMARK, DELIMITER) RICE_1_LIST5(MARK1, POSTMARK, DELIMITER) DELIMITER MARK1##6 POSTMARK
      #define RICE_1_LIST7(MARK1, POSTMARK, DELIMITER) RICE_1_LIST6(MARK1, POSTMARK, DELIMITER) DELIMITER MARK1##7 POSTMARK
      #define RICE_1_LIST8(MARK1, POSTMARK, DELIMITER) RICE_1_LIST7(MARK1, POSTMARK, DELIMITER) DELIMITER MARK1##8 POSTMARK
      #define RICE_1_LIST9(MARK1, POSTMARK, DELIMITER) RICE_1_LIST8(MARK1, POSTMARK, DELIMITER) DELIMITER MARK1##9 POSTMARK
      #define RICE_1_LIST10(MARK1, POSTMARK, DELIMITER) RICE_1_LIST9(MARK1, POSTMARK, DELIMITER) DELIMITER MARK1##10 POSTMARK
      #define RICE_1_LIST11(MARK1, POSTMARK, DELIMITER) RICE_1_LIST10(MARK1, POSTMARK, DELIMITER) DELIMITER MARK1##11 POSTMARK
      #define RICE_1_LIST12(MARK1, POSTMARK, DELIMITER) RICE_1_LIST11(MARK1, POSTMARK, DELIMITER) DELIMITER MARK1##12 POSTMARK
      #define RICE_1_LIST13(MARK1, POSTMARK, DELIMITER) RICE_1_LIST12(MARK1, POSTMARK, DELIMITER) DELIMITER MARK1##13 POSTMARK
      #define RICE_1_LIST14(MARK1, POSTMARK, DELIMITER) RICE_1_LIST13(MARK1, POSTMARK, DELIMITER) DELIMITER MARK1##14 POSTMARK
      #define RICE_1_LIST15(MARK1, POSTMARK, DELIMITER) RICE_1_LIST14(MARK1, POSTMARK, DELIMITER) DELIMITER MARK1##15 POSTMARK
      #define RICE_1_LIST16(MARK1, POSTMARK, DELIMITER) RICE_1_LIST15(MARK1, POSTMARK, DELIMITER) DELIMITER MARK1##16 POSTMARK
      #define RICE_1_LIST17(MARK1, POSTMARK, DELIMITER) RICE_1_LIST16(MARK1, POSTMARK, DELIMITER) DELIMITER MARK1##17 POSTMARK
      #define RICE_1_LIST18(MARK1, POSTMARK, DELIMITER) RICE_1_LIST17(MARK1, POSTMARK, DELIMITER) DELIMITER MARK1##18 POSTMARK
      #define RICE_1_LIST19(MARK1, POSTMARK, DELIMITER) RICE_1_LIST18(MARK1, POSTMARK, DELIMITER) DELIMITER MARK1##19 POSTMARK
      #define RICE_1_LIST20(MARK1, POSTMARK, DELIMITER) RICE_1_LIST19(MARK1, POSTMARK, DELIMITER) DELIMITER MARK1##20 POSTMARK
      #define RICE_1_LIST21(MARK1, POSTMARK, DELIMITER) RICE_1_LIST20(MARK1, POSTMARK, DELIMITER) DELIMITER MARK1##21 POSTMARK
      #define RICE_1_LIST22(MARK1, POSTMARK, DELIMITER) RICE_1_LIST21(MARK1, POSTMARK, DELIMITER) DELIMITER MARK1##22 POSTMARK
      #define RICE_1_LIST23(MARK1, POSTMARK, DELIMITER) RICE_1_LIST22(MARK1, POSTMARK, DELIMITER) DELIMITER MARK1##23 POSTMARK
      #define RICE_1_LIST24(MARK1, POSTMARK, DELIMITER) RICE_1_LIST23(MARK1, POSTMARK, DELIMITER) DELIMITER MARK1##24 POSTMARK
      #define RICE_1_LIST25(MARK1, POSTMARK, DELIMITER) RICE_1_LIST24(MARK1, POSTMARK, DELIMITER) DELIMITER MARK1##25 POSTMARK
      #define RICE_1_LIST26(MARK1, POSTMARK, DELIMITER) RICE_1_LIST25(MARK1, POSTMARK, DELIMITER) DELIMITER MARK1##26 POSTMARK
      #define RICE_1_LIST27(MARK1, POSTMARK, DELIMITER) RICE_1_LIST26(MARK1, POSTMARK, DELIMITER) DELIMITER MARK1##27 POSTMARK
      #define RICE_1_LIST28(MARK1, POSTMARK, DELIMITER) RICE_1_LIST27(MARK1, POSTMARK, DELIMITER) DELIMITER MARK1##28 POSTMARK
      #define RICE_1_LIST29(MARK1, POSTMARK, DELIMITER) RICE_1_LIST28(MARK1, POSTMARK, DELIMITER) DELIMITER MARK1##29 POSTMARK

      #define RICE_2_LIST0(MARK1, MARK2, POSTMARK, DELIMITER) MARK1##0 MARK2##0 POSTMARK
      #define RICE_2_LIST1(MARK1, MARK2, POSTMARK, DELIMITER) RICE_2_LIST0(MARK1, MARK2, POSTMARK, DELIMITER) DELIMITER MARK1##1 MARK2##1 POSTMARK
      #define RICE_2_LIST2(MARK1, MARK2, POSTMARK, DELIMITER) RICE_2_LIST1(MARK1, MARK2, POSTMARK, DELIMITER) DELIMITER MARK1##2 MARK2##2 POSTMARK
      #define RICE_2_LIST3(MARK1, MARK2, POSTMARK, DELIMITER) RICE_2_LIST2(MARK1, MARK2, POSTMARK, DELIMITER) DELIMITER MARK1##3 MARK2##3 POSTMARK
      #define RICE_2_LIST4(MARK1, MARK2, POSTMARK, DELIMITER) RICE_2_LIST3(MARK1, MARK2, POSTMARK, DELIMITER) DELIMITER MARK1##4 MARK2##4 POSTMARK
      #define RICE_2_LIST5(MARK1, MARK2, POSTMARK, DELIMITER) RICE_2_LIST4(MARK1, MARK2, POSTMARK, DELIMITER) DELIMITER MARK1##5 MARK2##5 POSTMARK
      #define RICE_2_LIST6(MARK1, MARK2, POSTMARK, DELIMITER) RICE_2_LIST5(MARK1, MARK2, POSTMARK, DELIMITER) DELIMITER MARK1##6 MARK2##6 POSTMARK
      #define RICE_2_LIST7(MARK1, MARK2, POSTMARK, DELIMITER) RICE_2_LIST6(MARK1, MARK2, POSTMARK, DELIMITER) DELIMITER MARK1##7 MARK2##7 POSTMARK
      #define RICE_2_LIST8(MARK1, MARK2, POSTMARK, DELIMITER) RICE_2_LIST7(MARK1, MARK2, POSTMARK, DELIMITER) DELIMITER MARK1##8 MARK2##8 POSTMARK
      #define RICE_2_LIST9(MARK1, MARK2, POSTMARK, DELIMITER) RICE_2_LIST8(MARK1, MARK2, POSTMARK, DELIMITER) DELIMITER MARK1##9 MARK2##9 POSTMARK
      #define RICE_2_LIST10(MARK1, MARK2, POSTMARK, DELIMITER) RICE_2_LIST9(MARK1, MARK2, POSTMARK, DELIMITER) DELIMITER MARK1##10 MARK2##10 POSTMARK
      #define RICE_2_LIST11(MARK1, MARK2, POSTMARK, DELIMITER) RICE_2_LIST10(MARK1, MARK2, POSTMARK, DELIMITER) DELIMITER MARK1##11 MARK2##11 POSTMARK
      #define RICE_2_LIST12(MARK1, MARK2, POSTMARK, DELIMITER) RICE_2_LIST11(MARK1, MARK2, POSTMARK, DELIMITER) DELIMITER MARK1##12 MARK2##12 POSTMARK
      #define RICE_2_LIST13(MARK1, MARK2, POSTMARK, DELIMITER) RICE_2_LIST12(MARK1, MARK2, POSTMARK, DELIMITER) DELIMITER MARK1##13 MARK2##13 POSTMARK
      #define RICE_2_LIST14(MARK1, MARK2, POSTMARK, DELIMITER) RICE_2_LIST13(MARK1, MARK2, POSTMARK, DELIMITER) DELIMITER MARK1##14 MARK2##14 POSTMARK
      #define RICE_2_LIST15(MARK1, MARK2, POSTMARK, DELIMITER) RICE_2_LIST14(MARK1, MARK2, POSTMARK, DELIMITER) DELIMITER MARK1##15 MARK2##15 POSTMARK
      #define RICE_2_LIST16(MARK1, MARK2, POSTMARK, DELIMITER) RICE_2_LIST15(MARK1, MARK2, POSTMARK, DELIMITER) DELIMITER MARK1##16 MARK2##16 POSTMARK
      #define RICE_2_LIST17(MARK1, MARK2, POSTMARK, DELIMITER) RICE_2_LIST16(MARK1, MARK2, POSTMARK, DELIMITER) DELIMITER MARK1##17 MARK2##17 POSTMARK
      #define RICE_2_LIST18(MARK1, MARK2, POSTMARK, DELIMITER) RICE_2_LIST17(MARK1, MARK2, POSTMARK, DELIMITER) DELIMITER MARK1##18 MARK2##18 POSTMARK
      #define RICE_2_LIST19(MARK1, MARK2, POSTMARK, DELIMITER) RICE_2_LIST18(MARK1, MARK2, POSTMARK, DELIMITER) DELIMITER MARK1##19 MARK2##19 POSTMARK
      #define RICE_2_LIST20(MARK1, MARK2, POSTMARK, DELIMITER) RICE_2_LIST19(MARK1, MARK2, POSTMARK, DELIMITER) DELIMITER MARK1##20 MARK2##20 POSTMARK
      #define RICE_2_LIST21(MARK1, MARK2, POSTMARK, DELIMITER) RICE_2_LIST20(MARK1, MARK2, POSTMARK, DELIMITER) DELIMITER MARK1##21 MARK2##21 POSTMARK
      #define RICE_2_LIST22(MARK1, MARK2, POSTMARK, DELIMITER) RICE_2_LIST21(MARK1, MARK2, POSTMARK, DELIMITER) DELIMITER MARK1##22 MARK2##22 POSTMARK
      #define RICE_2_LIST23(MARK1, MARK2, POSTMARK, DELIMITER) RICE_2_LIST22(MARK1, MARK2, POSTMARK, DELIMITER) DELIMITER MARK1##23 MARK2##23 POSTMARK
      #define RICE_2_LIST24(MARK1, MARK2, POSTMARK, DELIMITER) RICE_2_LIST23(MARK1, MARK2, POSTMARK, DELIMITER) DELIMITER MARK1##24 MARK2##24 POSTMARK
      #define RICE_2_LIST25(MARK1, MARK2, POSTMARK, DELIMITER) RICE_2_LIST24(MARK1, MARK2, POSTMARK, DELIMITER) DELIMITER MARK1##25 MARK2##25 POSTMARK
      #define RICE_2_LIST26(MARK1, MARK2, POSTMARK, DELIMITER) RICE_2_LIST25(MARK1, MARK2, POSTMARK, DELIMITER) DELIMITER MARK1##26 MARK2##26 POSTMARK
      #define RICE_2_LIST27(MARK1, MARK2, POSTMARK, DELIMITER) RICE_2_LIST26(MARK1, MARK2, POSTMARK, DELIMITER) DELIMITER MARK1##27 MARK2##27 POSTMARK
      #define RICE_2_LIST28(MARK1, MARK2, POSTMARK, DELIMITER) RICE_2_LIST27(MARK1, MARK2, POSTMARK, DELIMITER) DELIMITER MARK1##28 MARK2##28 POSTMARK
      #define RICE_2_LIST29(MARK1, MARK2, POSTMARK, DELIMITER) RICE_2_LIST28(MARK1, MARK2, POSTMARK, DELIMITER) DELIMITER MARK1##29 MARK2##29 POSTMARK

      #define RICE_3_LIST0(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) MARK1##0 MARK2##0 MARK3##0 POSTMARK
      #define RICE_3_LIST1(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) RICE_3_LIST0(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) DELIMITER MARK1##1 MARK2##1 MARK3##1 POSTMARK
      #define RICE_3_LIST2(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) RICE_3_LIST1(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) DELIMITER MARK1##2 MARK2##2 MARK3##2 POSTMARK
      #define RICE_3_LIST3(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) RICE_3_LIST2(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) DELIMITER MARK1##3 MARK2##3 MARK3##3 POSTMARK
      #define RICE_3_LIST4(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) RICE_3_LIST3(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) DELIMITER MARK1##4 MARK2##4 MARK3##4 POSTMARK
      #define RICE_3_LIST5(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) RICE_3_LIST4(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) DELIMITER MARK1##5 MARK2##5 MARK3##5 POSTMARK
      #define RICE_3_LIST6(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) RICE_3_LIST5(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) DELIMITER MARK1##6 MARK2##6 MARK3##6 POSTMARK
      #define RICE_3_LIST7(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) RICE_3_LIST6(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) DELIMITER MARK1##7 MARK2##7 MARK3##7 POSTMARK
      #define RICE_3_LIST8(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) RICE_3_LIST7(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) DELIMITER MARK1##8 MARK2##8 MARK3##8 POSTMARK
      #define RICE_3_LIST9(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) RICE_3_LIST8(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) DELIMITER MARK1##9 MARK2##9 MARK3##9 POSTMARK
      #define RICE_3_LIST10(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) RICE_3_LIST9(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) DELIMITER MARK1##10 MARK2##10 MARK3##10 POSTMARK
      #define RICE_3_LIST11(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) RICE_3_LIST10(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) DELIMITER MARK1##11 MARK2##11 MARK3##11 POSTMARK
      #define RICE_3_LIST12(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) RICE_3_LIST11(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) DELIMITER MARK1##12 MARK2##12 MARK3##12 POSTMARK
      #define RICE_3_LIST13(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) RICE_3_LIST12(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) DELIMITER MARK1##13 MARK2##13 MARK3##13 POSTMARK
      #define RICE_3_LIST14(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) RICE_3_LIST13(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) DELIMITER MARK1##14 MARK2##14 MARK3##14 POSTMARK
      #define RICE_3_LIST15(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) RICE_3_LIST14(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) DELIMITER MARK1##15 MARK2##15 MARK3##15 POSTMARK
      #define RICE_3_LIST16(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) RICE_3_LIST15(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) DELIMITER MARK1##16 MARK2##16 MARK3##16 POSTMARK
      #define RICE_3_LIST17(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) RICE_3_LIST16(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) DELIMITER MARK1##17 MARK2##17 MARK3##17 POSTMARK
      #define RICE_3_LIST18(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) RICE_3_LIST17(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) DELIMITER MARK1##18 MARK2##18 MARK3##18 POSTMARK
      #define RICE_3_LIST19(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) RICE_3_LIST18(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) DELIMITER MARK1##19 MARK2##19 MARK3##19 POSTMARK
      #define RICE_3_LIST20(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) RICE_3_LIST19(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) DELIMITER MARK1##20 MARK2##20 MARK3##20 POSTMARK
      #define RICE_3_LIST21(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) RICE_3_LIST20(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) DELIMITER MARK1##21 MARK2##21 MARK3##21 POSTMARK
      #define RICE_3_LIST22(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) RICE_3_LIST21(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) DELIMITER MARK1##22 MARK2##22 MARK3##22 POSTMARK
      #define RICE_3_LIST23(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) RICE_3_LIST22(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) DELIMITER MARK1##23 MARK2##23 MARK3##23 POSTMARK
      #define RICE_3_LIST24(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) RICE_3_LIST23(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) DELIMITER MARK1##24 MARK2##24 MARK3##24 POSTMARK
      #define RICE_3_LIST25(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) RICE_3_LIST24(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) DELIMITER MARK1##25 MARK2##25 MARK3##25 POSTMARK
      #define RICE_3_LIST26(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) RICE_3_LIST25(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) DELIMITER MARK1##26 MARK2##26 MARK3##26 POSTMARK
      #define RICE_3_LIST27(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) RICE_3_LIST26(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) DELIMITER MARK1##27 MARK2##27 MARK3##27 POSTMARK
      #define RICE_3_LIST28(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) RICE_3_LIST27(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) DELIMITER MARK1##28 MARK2##28 MARK3##28 POSTMARK
      #define RICE_3_LIST29(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) RICE_3_LIST28(MARK1, MARK2, MARK3, POSTMARK, DELIMITER) DELIMITER MARK1##29 MARK2##29 MARK3##29 POSTMARK

      #define RICE_MACRO_LIST0(MACRO) MACRO(0)
      #define RICE_MACRO_LIST1(MACRO) RICE_MACRO_LIST0(MACRO); MACRO(1)
      #define RICE_MACRO_LIST2(MACRO) RICE_MACRO_LIST1(MACRO); MACRO(2)
      #define RICE_MACRO_LIST3(MACRO) RICE_MACRO_LIST2(MACRO); MACRO(3)
      #define RICE_MACRO_LIST4(MACRO) RICE_MACRO_LIST3(MACRO); MACRO(4)
      #define RICE_MACRO_LIST5(MACRO) RICE_MACRO_LIST4(MACRO); MACRO(5)
      #define RICE_MACRO_LIST6(MACRO) RICE_MACRO_LIST5(MACRO); MACRO(6)
      #define RICE_MACRO_LIST7(MACRO) RICE_MACRO_LIST6(MACRO); MACRO(7)
      #define RICE_MACRO_LIST8(MACRO) RICE_MACRO_LIST7(MACRO); MACRO(8)
      #define RICE_MACRO_LIST9(MACRO) RICE_MACRO_LIST8(MACRO); MACRO(9)
      #define RICE_MACRO_LIST10(MACRO) RICE_MACRO_LIST9(MACRO); MACRO(10)
      #define RICE_MACRO_LIST11(MACRO) RICE_MACRO_LIST10(MACRO); MACRO(11)
      #define RICE_MACRO_LIST12(MACRO) RICE_MACRO_LIST11(MACRO); MACRO(12)
      #define RICE_MACRO_LIST13(MACRO) RICE_MACRO_LIST12(MACRO); MACRO(13)
      #define RICE_MACRO_LIST14(MACRO) RICE_MACRO_LIST13(MACRO); MACRO(14)
      #define RICE_MACRO_LIST15(MACRO) RICE_MACRO_LIST14(MACRO); MACRO(15)
      #define RICE_MACRO_LIST16(MACRO) RICE_MACRO_LIST15(MACRO); MACRO(16)
      #define RICE_MACRO_LIST17(MACRO) RICE_MACRO_LIST16(MACRO); MACRO(17)
      #define RICE_MACRO_LIST18(MACRO) RICE_MACRO_LIST17(MACRO); MACRO(18)
      #define RICE_MACRO_LIST19(MACRO) RICE_MACRO_LIST18(MACRO); MACRO(19)
      #define RICE_MACRO_LIST20(MACRO) RICE_MACRO_LIST19(MACRO); MACRO(20)
      #define RICE_MACRO_LIST21(MACRO) RICE_MACRO_LIST20(MACRO); MACRO(21)
      #define RICE_MACRO_LIST22(MACRO) RICE_MACRO_LIST21(MACRO); MACRO(22)
      #define RICE_MACRO_LIST23(MACRO) RICE_MACRO_LIST22(MACRO); MACRO(23)
      #define RICE_MACRO_LIST24(MACRO) RICE_MACRO_LIST23(MACRO); MACRO(24)
      #define RICE_MACRO_LIST25(MACRO) RICE_MACRO_LIST24(MACRO); MACRO(25)
      #define RICE_MACRO_LIST26(MACRO) RICE_MACRO_LIST25(MACRO); MACRO(26)
      #define RICE_MACRO_LIST27(MACRO) RICE_MACRO_LIST26(MACRO); MACRO(27)
      #define RICE_MACRO_LIST28(MACRO) RICE_MACRO_LIST27(MACRO); MACRO(28)
      #define RICE_MACRO_LIST29(MACRO) RICE_MACRO_LIST28(MACRO); MACRO(29)

      #define RICE_EMPTY
      #define RICE_COMMA ,
      #define RICE_OPEN_PAREN (
      #define RICE_CLOSE_PAREN )

      #endif

       
    • Matthew Elkins

      Matthew Elkins - 2009-01-30

      #ifndef RICE_STATIC_H
      #define RICE_STATIC_H

      #include <climits>
      #include "ListMacros.h"

      namespace Rice
      {
          // Static NULL type has nested StackAction so it can be reused as a no-op stack action
          struct NullType {struct StackAction {};};

          // Static Math
          template <int Base, unsigned int Exponent> struct StaticPower {enum {Result = Base * StaticPower<Base, Exponent - 1>::Result};};
          template <int Base> struct StaticPower<Base, 0> {enum {Result = 1};};

          // Static Logic
          template <bool Condition, typename LHS, typename RHS> struct TypeSwitch {typedef LHS Result;};
          template <typename LHS, typename RHS> struct TypeSwitch<false, LHS, RHS> {typedef RHS Result;};

          template <bool Condition, int LHS, int RHS> struct ValueSwitch {enum {Result = LHS};};
          template <int LHS, int RHS> struct ValueSwitch<false, LHS, RHS> {enum {Result = RHS};};

          template <typename T, typename U> struct SameTypes {enum {Result = false};};
          template <typename T> struct SameTypes<T, T> {enum {Result = true};};

          template <RICE_1_LIST29(typename T, = NullType, RICE_COMMA)> class Params
          {
              friend class Params;

              typedef typename Params
              <
                   T1,  T2,  T3,  T4,  T5,  T6,  T7,  T8,  T9, T10,
                  T11, T12, T13, T14, T15, T16, T17, T18, T19, T20,
                  T21, T22, T23, T24, T25, T26, T27, T28, T29
              > NextList;

              typedef typename Params <RICE_1_LIST29(T, RICE_EMPTY, RICE_COMMA)> ThisList;

              template <typename THIS, typename NEXT> struct TypeListNode
              {
                  typedef THIS This;
                  typedef NEXT Next;
              };

              typedef TypeListNode<T0, typename NextList::Type> Type;

              template <typename T> struct PushOneFront {typedef typename Params<T, RICE_1_LIST28(T, RICE_EMPTY, RICE_COMMA)> Result;};
              template <typename T> struct ContainsOne {enum {Result = (SameTypes<T, Front>::Result || PopFront::ContainsOne<T>::Result)};};

              public:
                  /// Slice: Specifies a 'slice' of this Params as a Params
                  template <size_t Start, size_t Count> struct Slice {typedef typename NextList::Slice<Start - 1, Count>::Result Result;};
                  template <size_t Count> struct Slice<0, Count> {typedef typename NextList::Slice<0, Count - 1>::Result::PushOneFront<Type::This>::Result Result;};
                  template <> struct Slice<0, 0> {typedef Params<> Result;};

                  /// Front: Specifies the front type of this Params
                  /// PopFront: Specifies all of this Params except the front type
                  typedef typename Type::This Front;
                  typedef typename NextList PopFront;
                 
                  /// Count: Specifies the number of genuine types in the Params
                  enum {Count = 1 + PopFront::Count};

                  /// Back: Specifies the back type of the Params
                  /// PopBack: Specifies all of this Params except the back type
                  typedef typename Slice<ValueSwitch<Count == 0, 0, Count - 1>::Result, 1>::Result::Front Back;
                  typedef typename Slice<0, ValueSwitch<Count == 0, 0, Count - 1>::Result>::Result PopBack;

                  /// Lookup: Specifies a type in the Params by index
                  template <size_t Index> struct Lookup {typedef typename Slice<Index, 1>::Result::Front Result;};

                  /// Split: Specifies two TypeLists split from this Params by index
                  template <size_t Index> struct Split
                  {
                      typedef typename Slice<0, Index>::Result LeftSide;
                      typedef typename Slice<Index, Count - Index>::Result RightSide;
                  };

                  /// Insert: Inserts a Params into this Params at the given index
                  template <size_t Index, class TList> struct Insert {typedef typename Split<Index>::RightSide::Insert<0, TList>::Result::Insert<0, Split<Index>::LeftSide>::Result Result;};
                  template <class TList> struct Insert<0, TList> {typedef typename PushOneFront<typename TList::Back>::Result::Insert<0, typename TList::PopBack>::Result Result;};
                  template <size_t Index> struct Insert<Index, Params<> > {typedef ThisList Result;};
                  template <> struct Insert<0, Params<> > {typedef ThisList Result;};

                  /// PushFront: Inserts a Params before this Params; equivalent to Insert with Index equal to 0
                  /// PushBack: Inserts a Params after this Params; equivalent to Insert with Index equal to Count
                  template <class TList> struct PushFront {typedef typename Insert<0, TList>::Result Result;};
                  template <class TList> struct PushBack {typedef typename Insert<Count, TList>::Result Result;};

                  /// Erase: Erases type at Index from this Params
                  template <size_t Index> struct Erase {typedef typename Split<Index>::LeftSide::PushBack<typename Split<Index>::RightSide::PopFront>::Result Result;};

                  template <class TList> struct Contains {enum {Result = (ContainsOne<typename TList::Front>::Result && Contains<typename TList::PopFront>::Result)};};
                  template <> struct Contains<Params<> > {enum {Result = true};};
          };

          template <> class Params<>
          {
              friend class Params;

              typedef NullType Type;

              template <typename T> struct PushOneFront {typedef typename Params<T> Result;};
              template <typename T> struct ContainsOne {enum {Result = false};};

              public:
                  template <size_t Start, size_t Count> struct Slice {typedef typename Params<> Result;};

                  typedef NullType Front;
                  typedef NullType Back;

                  template <size_t Index> struct Lookup {typedef NullType Result;};

                  typedef Params<> PopFront;
                  typedef Params<> PopBack;

                  enum {Count = 0};

                  template <size_t Index> struct Split
                  {
                      typedef typename Params<> LeftSide;
                      typedef typename Params<> RightSide;
                  };

                  template <size_t Index, class TList> struct Insert {typedef typename Split<Index>::RightSide::Insert<0, TList>::Result::Insert<0, Split<Index>::LeftSide>::Result Result;};
                  template <class TList> struct Insert<0, TList> {typedef typename PushOneFront<typename TList::Back>::Result::Insert<0, typename TList::PopBack>::Result Result;};
                  template <size_t Index> struct Insert<Index, Params<> > {typedef Params<> Result;};
                  template <> struct Insert<0, Params<> > {typedef Params<> Result;};

                  template <typename TList> struct PushFront {typedef typename Insert<0, TList>::Result Result;};
                  template <typename TList> struct PushBack {typedef typename Insert<Count, TList>::Result Result;};
          };

          template <typename T> struct ExtractRawType {typedef T Result;};
          template <typename T> struct ExtractRawType<T&> {typedef T Result;};
          template <typename T> struct ExtractRawType<T*> {typedef T Result;};
          template <typename T> struct ExtractRawType<const T&> {typedef T Result;};
          template <typename T> struct ExtractRawType<const T*> {typedef T Result;};

          template <typename T> struct AddReference {typedef T& Result;};
          template <typename T> struct AddReference<T&> {typedef T& Result;};
          template <typename T> struct AddReference<const T&> {typedef const T& Result;};

          template <typename T> struct AddReferenceFavorConst {typedef const T& Result;};
          template <typename T> struct AddReferenceFavorConst<T&> {typedef T& Result;};
          template <typename T> struct AddReferenceFavorConst<const T&> {typedef const T& Result;};

          template <typename T> struct AddConstReference {typedef const T& Result;};
          template <typename T> struct AddConstReference<T&> {typedef const T& Result;};
          template <typename T> struct AddConstReference<const T&> {typedef const T& Result;};

          template <typename T> struct IsReference {enum {Result = false};};
          template <typename T> struct IsReference<T&> {enum {Result = true};};
          template <typename T> struct IsReference<const T&> {enum {Result = true};};

          template <typename T> struct IsPointer {enum {Result = false};};
          template <typename T> struct IsPointer<T*> {enum {Result = true};};
          template <typename T> struct IsPointer<const T*> {enum {Result = true};};
         
          template <typename T> struct IsSignedInteger {enum {Result = Params<char, short, int, long>::Contains<Params<T> >::Result};};
          template <typename T> struct IsUnsignedInteger {enum {Result = Params<wchar_t, unsigned char, unsigned short, unsigned int, unsigned long>::Contains<Params<T> >::Result};};
          template <typename T> struct IsDecimal {enum {Result = Params<float, double>::Contains<Params<T> >::Result};};
          template <typename T> struct IsInteger {enum {Result = IsSignedInteger<T>::Result || IsUnsignedInteger<T>::Result};};
          template <typename T> struct IsNumber {enum {Result = IsInteger<T>::Result || IsDecimal<T>::Result};};
          template <typename T> struct IsPrimitive {enum {Result = IsNumber<T>::Result || IsReference<T>::Result || IsPointer<T>::Result};};

          template <typename T> struct IsCopyTrivial {enum {Result = IsPrimitive<T>::Result};};
          template <typename T> struct FastParam {typedef typename TypeSwitch<(sizeof(T) <= sizeof(long) && IsCopyTrivial<T>::Result), T, typename AddReferenceFavorConst<T>::Result>::Result Result;};

          // Static Traits
          template <typename T> struct Traits
          {
              enum {NumberOfBits = sizeof(T) * CHAR_BIT};
              enum {IsReference = IsReference<T>::Result};
              enum {IsPointer = IsPointer<T>::Result};
              enum {IsPrimitive = IsPrimitive<T>::Result};
              enum {IsNumber = IsNumber<T>::Result};
              enum {IsInteger = IsInteger<T>::Result};
              enum {IsDecimal = IsDecimal<T>::Result};
              enum {IsUnsignedInteger = IsUnsignedInteger<T>::Result};
              enum {IsSignedInteger = IsSignedInteger<T>::Result};

              typedef typename AddReference<T>::Result AddReference;
              typedef typename AddReferenceFavorConst<T>::Result AddReferenceFavorConst;
              typedef typename AddConstReference<T>::Result AddConstReference;
              typedef typename FastParam<T>::Result FastParam;
              typedef typename ExtractRawType<T>::Result RawType;

              template <typename U> struct SameType {enum {Result = SameTypes<T, U>::Result};};
          };
      }

      #endif

       
    • Matthew Elkins

      Matthew Elkins - 2009-01-30

      #ifndef RICE_ARGLIST_H
      #define RICE_ARGLIST_H

      #include "ListMacros.h"
      #include "Static.h"

      namespace Rice
      {
          template <class Parameters> class ArgList : public ArgList<typename Parameters::PopFront>
          {
              typedef typename ArgList<typename Parameters::PopFront> Base;
              typedef typename Parameters::Front ThisType;

              public:
                  explicit ArgList(typename Parameters::Lookup<0>::Result param) : m_param(param) {}

                  #define RICE_ARGLIST_CONSTRUCTOR(NUM)                                                                                                                        \             ArgList(typename Parameters::Lookup<0>::Result param RICE_2_LIST##NUM##(RICE_COMMA typename Parameters::Lookup<1 +, >::Result t, RICE_EMPTY, RICE_EMPTY)) :    \                 Base(RICE_1_LIST##NUM##(t, RICE_EMPTY, RICE_COMMA)), m_param(param) {}

                  RICE_MACRO_LIST29(RICE_ARGLIST_CONSTRUCTOR)
                  #undef RICE_ARGLIST_CONSTRUCTOR

                  enum {Count = 1 + Base::Count};

                  template <size_t Index> struct TypeAt {typedef typename Base::TypeAt<Index - 1>::Result Result;};
                  template <> struct TypeAt<0> {typedef typename ThisType Result;};
                 
                  template <size_t Index> typename TypeAt<Index>::Result Arg() const {return Base::Arg<Index - 1>();}
                  template <> typename TypeAt<0>::Result Arg<0>() const {return m_param;}
             
              private:
                  ThisType m_param;
          };

          template <> class ArgList<Params<> >
          {
              public:
                  enum {Count = 0};
          };
      }

      #endif

       
    • Matthew Elkins

      Matthew Elkins - 2009-01-30

      #ifndef RICE_BINDERLIST_H
      #define RICE_BINDERLIST_H

      #include "Static.h"

      namespace Rice
      {
          template <typename T> class ByValHelper
          {
              public:
                  explicit ByValHelper(typename Traits<T>::FastParam val) : m_val(val) {}
                  operator T&() const {return m_val;}

              private:
                  mutable T m_val;
          };

          template <typename T> class ByRefHelper
          {
              public:
                  explicit ByRefHelper(T & ref) : m_ref(&ref) {}
                  operator T&() const {return *m_ref;}

              private:
                  T * m_ref;
          };

          template <size_t Index, typename Parameter> struct Binder
          {
              enum {Pos = Index};
              typedef Parameter P;
              explicit Binder(typename Traits<P>::FastParam p) : Param(p) {}
              P Param;
          };
          typedef Binder<0, int> NullBinder;

          template <size_t Index, typename Parameter> Binder<Index, Parameter> Bind(Parameter param) {return Binder<Index, Parameter>(param);}
          template <size_t Index, typename Parameter> Binder<Index, ByValHelper<Parameter> > BindVal(Parameter param) {return Binder<Index, ByValHelper<Parameter> >(ByValHelper<Parameter>(param));}
          template <size_t Index, typename Parameter> Binder<Index, ByRefHelper<Parameter> > BindRef(Parameter & param) {return Binder<Index, ByRefHelper<Parameter> >(ByRefHelper<Parameter>(param));}

              template <class Parameters> class BinderList : public BinderList<typename Parameters::PopFront>
          {
              typedef typename BinderList<typename Parameters::PopFront> Base;
              typedef typename Traits<typename Parameters::Front>::RawType ThisBinder;
              typedef typename ThisBinder::P ThisType;
              enum {ThisIndex = ThisBinder::Pos};

              public:
                  explicit BinderList(typename Parameters::Lookup<0>::Result param) : m_param(param.Param) {}

                  #define RICE_BINDERLIST_CONSTRUCTOR(NUM)                                                                                                                        \             BinderList(typename Parameters::Lookup<0>::Result param RICE_2_LIST##NUM##(RICE_COMMA typename Parameters::Lookup<1 +, >::Result t, RICE_EMPTY, RICE_EMPTY)) :    \                 Base(RICE_1_LIST##NUM##(t, RICE_EMPTY, RICE_COMMA)), m_param(param.Param) {}

                  RICE_MACRO_LIST29(RICE_BINDERLIST_CONSTRUCTOR)
                  #undef RICE_BINDERLIST_CONSTRUCTOR

                  enum {Count = Parameters::Count};
                  template <size_t Index> struct HasIndex {enum {Result = ((Index == ThisIndex) || Base::HasIndex<Index>::Result)};};
                  template <size_t Index> struct IndicesBelow {enum {Result = ((ThisIndex < Index ? 1 : 0) + Base::IndicesBelow<Index>::Result)};};
                 
                  template <size_t Index> struct TypeAt {typedef typename Base::TypeAt<Index>::Result Result;};
                  template <> struct TypeAt<ThisIndex> {typedef typename Traits<ThisType>::FastParam Result;};
                 
                  template <size_t Index> typename TypeAt<Index>::Result Arg() const {return Base::Arg<Index>();}
                  template <> typename TypeAt<ThisIndex>::Result Arg<ThisIndex>() const {return m_param;}

                  bool operator==(const BinderList & other) const {return (m_param == other.m_param && Base::operator==(other));}

              private:
                  ThisType m_param;
          };

          template <> class BinderList<Params<> >
          {
              public:
                  enum {Count = 0};
                  template <size_t Index> struct HasIndex {enum {Result = false};};
                  template <size_t Index> struct IndicesBelow {enum {Result = 0};};
                  bool operator==(const BinderList &) const {return true;}
          };
      }

      #endif

       
    • Matthew Elkins

      Matthew Elkins - 2009-01-30

      #ifndef RICE_FUNCTOR_H
      #define RICE_FUNCTOR_H

      #include "ListMacros.h"
      #include "Static.h"
      #include "SmartPtr.h"
      #include "FunctorImp.h"
      #include "ArgList.h"
      #include "BinderList.h"
      #include "Method.h"

      namespace Rice
      {
          template <typename Return, class Parameters> class FunctorBase;

          #ifdef RICE_RTTI
          #define RICE_FUNCTORBASE_EQUALITY_IMP                                                        \     bool operator==(const FunctorBase & other) const {return (*m_functor == *other.m_functor);}    \     bool operator!=(const FunctorBase & other) const {return !(*this == other);}
          #else
          #define RICE_FUNCTORBASE_EQUALITY_IMP
          #endif

          template <typename Return> class FunctorBase<Return, Params<> >
          {
              typedef Params<> CallingParams;

              public:
                  Return operator()() const {return (*m_functor)(ArgList<CallingParams>());}
                  RICE_FUNCTORBASE_EQUALITY_IMP

              protected:
                  explicit FunctorBase(FunctorImp<Return, CallingParams> * functor) : m_functor(functor) {}
                  FunctorBase(const FunctorBase & other) : m_functor(other.m_functor) {}
                  ~FunctorBase() {}
                  void operator=(const FunctorBase &) {m_functor = other.m_functor;}

              private:
                  SmartPtr<FunctorImp<Return, CallingParams>, Duplicate, ScalarClone> m_functor;
          };

          #define RICE_FUNCTORBASE_IMP(NUM)                                                                        \     template <typename Return, RICE_1_LIST##NUM##(typename T, RICE_EMPTY, RICE_COMMA)>                        \     class FunctorBase<Return, Params<RICE_1_LIST##NUM##(T, RICE_EMPTY, RICE_COMMA)> >                        \     {                                                                                                        \         typedef Params<RICE_1_LIST##NUM##(T, RICE_EMPTY, RICE_COMMA)> CallingParams;                        \                                                                                                             \         public:                                                                                                \             Return operator()(RICE_2_LIST##NUM##(T, t, RICE_EMPTY, RICE_COMMA)) const                        \             {                                                                                                \                 return (*m_functor)(ArgList<CallingParams>(RICE_1_LIST##NUM##(t, RICE_EMPTY, RICE_COMMA)));    \             }                                                                                                \             RICE_FUNCTORBASE_EQUALITY_IMP                                                                    \                                                                                                             \         protected:                                                                                            \             explicit FunctorBase(FunctorImp<Return, CallingParams> * functor) : m_functor(functor) {}        \             FunctorBase(const FunctorBase & other) : m_functor(other.m_functor) {}                            \             ~FunctorBase() {}                                                                                \             void operator=(const FunctorBase &) {m_functor = other.m_functor;}                                \                                                                                                             \         private:                                                                                            \             SmartPtr<FunctorImp<Return, CallingParams>, Duplicate, ScalarClone> m_functor;                    \     }

          RICE_MACRO_LIST29(RICE_FUNCTORBASE_IMP);

          #undef RICE_FUNCTORBASE_IMP
          #undef RICE_FUNCTORBASE_EQUALITY_IMP

          template <class Parameters> struct MakeParamsFast
          {
              typedef typename Traits<typename Parameters::Front>::FastParam FastFront;
              typedef typename MakeParamsFast<typename Parameters::PopFront>::Result::PushFront<Params<FastFront> >::Result Result;
          };
          template <> struct MakeParamsFast<Params<> >
          {
              typedef Params<> Result;
          };

          template <typename Return = void, class Parameters = Params<> > class Functor : public FunctorBase<Return, typename MakeParamsFast<Parameters>::Result>
          {
              typedef typename MakeParamsFast<Parameters>::Result FastParams;

              public:
                  template <typename Fun> Functor(Fun fun) : FunctorBase(new FunctorFinalImp<Return, Fun, FastParams, BinderList<Params<> > >(fun, BinderList<Params<> >())) {}
                  template <typename Obj, typename Fun> Functor(Obj & obj, Fun fun) : FunctorBase(new FunctorFinalImp<Return, Method<Return, Obj, Fun>, FastParams, BinderList<Params<> > >(Bind<Return>(obj, fun), BinderList<Params<> >())) {}

                  #define RICE_FUNCTOR_CONSTRUCTOR(NUM)                                                                                                                                    \             template <typename Fun, RICE_1_LIST##NUM##(size_t I, RICE_EMPTY, RICE_COMMA), RICE_1_LIST##NUM##(typename B, RICE_EMPTY, RICE_COMMA)>                                    \             Functor(Fun fun, RICE_3_LIST##NUM##(Binder<I, RICE_COMMA B, > b, RICE_EMPTY, RICE_COMMA)) :                                                                                \             FunctorBase(new FunctorFinalImp<Return, Fun, FastParams, BinderList<Params<RICE_2_LIST##NUM##(typename Traits<Binder<I, RICE_COMMA B, > >::FastParam, RICE_COMMA) > > >                                \             (fun, BinderList<Params<RICE_2_LIST##NUM##(typename Traits<Binder<I, RICE_COMMA B, > >::FastParam, RICE_COMMA) > >(RICE_1_LIST##NUM##(b, RICE_EMPTY, RICE_COMMA)))) {}    \                                                                                                                                                                                     \             template <typename Obj, typename Fun, RICE_1_LIST##NUM##(size_t I, RICE_EMPTY, RICE_COMMA), RICE_1_LIST##NUM##(typename B, RICE_EMPTY, RICE_COMMA)>                        \             Functor(Obj & obj, Fun fun, RICE_3_LIST##NUM##(Binder<I, RICE_COMMA B, > b, RICE_EMPTY, RICE_COMMA)) :                                                                    \             FunctorBase(new FunctorFinalImp<Return, Method<Return, Obj, Fun>, FastParams, BinderList<Params<RICE_2_LIST##NUM##(typename Traits<Binder<I, RICE_COMMA B, > >::FastParam, RICE_COMMA) > > >            \             (Bind<Return>(obj, fun), BinderList<Params<RICE_2_LIST##NUM##(typename Traits<Binder<I, RICE_COMMA B, > >::FastParam, RICE_COMMA) > >(RICE_1_LIST##NUM##(b, RICE_EMPTY, RICE_COMMA)))) {}

                  RICE_MACRO_LIST29(RICE_FUNCTOR_CONSTRUCTOR)
                  #undef RICE_FUNCTOR_CONSTRUCTOR
          };
      }

      #endif

       
    • Matthew Elkins

      Matthew Elkins - 2009-01-30

      #ifndef RICE_FUNCTORIMP_H
      #define RICE_FUNCTORIMP_H

      #include "ListMacros.h"
      #include "Static.h"
      #include "SmallAllocator.h"
      #include "ArgList.h"
      #include "BinderList.h"

      namespace Rice
      {
          template <size_t Index, class Args, class Binders> struct ParamResolver
          {
              typedef typename Traits<Args>::RawType ArgsType;
              typedef typename Traits<Binders>::RawType BindersType;

              enum {InBinders = BindersType::HasIndex<Index>::Result};

              // If the binders have the index, use it directly from them
              // If the binders do not have the index, the args must; use the index less any previously-bound indices
              enum {MappedIndex = ValueSwitch<InBinders, Index, Index - BindersType::IndicesBelow<Index>::Result>::Result};

              // If the binders have the index, use the MappedIndex from them to resolve the type
              // If the binders do not have the index, the args must; use the MappedIndex from them to resolve the type
              typedef typename TypeSwitch<InBinders, BindersType, ArgsType>::Result::TypeAt<MappedIndex>::Result Type;

              template <bool InBinders> static Type GetArgFromList(Args, Binders binders) {return binders.Arg<MappedIndex>();}
              template <> static Type GetArgFromList<false>(Args args, Binders) {return args.Arg<MappedIndex>();}

              static Type GetArg(Args args, Binders binders) {return GetArgFromList<InBinders>(args, binders);}
          };

          template <size_t Index, class Args, class Binders> typename ParamResolver<Index, Args, Binders>::Type Resolve(Args args, const Binders binders)
          {
              return ParamResolver<Index, Args, Binders>::GetArg(args, binders);
          }

          template <size_t Count, typename Return, typename Fun, class Args, class Binders> struct FunctionCaller;
          template <typename Return, typename Fun, class Args, class Binders> struct FunctionCaller<0, Return, Fun, Args, Binders> {static Return Call(Fun fun, Args, Binders) {return fun();}};

          #define RICE_FUNCTIONCALLER_IMP(NUM)                                                                                                                        \     template <typename Return, typename Fun, class Args, class Binders> struct FunctionCaller<NUM + 1, Return, Fun, Args, Binders>                                \     {                                                                                                                                                            \         static Return Call(Fun fun, Args args, Binders binders)                                                                                                    \         {                                                                                                                                                        \             return fun(RICE_1_LIST##NUM##(Resolve<, RICE_COMMA Args RICE_COMMA Binders> RICE_OPEN_PAREN args RICE_COMMA binders RICE_CLOSE_PAREN, RICE_COMMA));    \         }                                                                                                                                                        \     }

          RICE_MACRO_LIST29(RICE_FUNCTIONCALLER_IMP);

          template <typename Return, typename Fun, class Args, class Binders> Return CallFunction(Fun fun, Args args, Binders binders)
          {
              return FunctionCaller<Traits<Args>::RawType::Count + Traits<Binders>::RawType::Count, Return, Fun, Args, Binders>::Call(fun, args, binders);
          }

          template <typename Return, class Parameters> class FunctorImp : public UseSmallAllocator
          {
              public:
                  typedef typename Traits<ArgList<Parameters> >::FastParam FastArgList;
                  typedef SmartPtr<FunctorImp> AutoPtr;
                  virtual ~FunctorImp() {}
                  virtual Return operator()(FastArgList args) const = 0;
                  virtual AutoPtr Clone() const = 0;

                  #ifdef RICE_RTTI
                  virtual bool operator==(const FunctorImp &) const = 0;
                  #endif

              protected:
                  FunctorImp() {}
                  FunctorImp(const FunctorImp &) {}
                  FunctorImp & operator=(const FunctorImp &) {return *this;}
          };

          template <typename Return, class Parameters, class Binders> class FunctorMiddleImp : public FunctorImp<Return, Parameters>
          {
              public:
                  typedef typename Traits<Binders>::FastParam FastBinders;
                  explicit FunctorMiddleImp(FastBinders binders) : m_binders(binders) {}

              protected:
                  FastBinders GetBinders() const {return m_binders;}
                  bool operator==(const FunctorMiddleImp & other) const {return (m_binders == other.m_binders);}

              private:
                  Binders m_binders;
          };

          template <typename Return, class Parameters> class FunctorMiddleImp<Return, Parameters, BinderList<Params<> > > : public FunctorImp<Return, Parameters>
          {
              public:
                  typedef BinderList<Params<> > FastBinders;
                  explicit FunctorMiddleImp(FastBinders) {}

              protected:
                  FastBinders GetBinders() const {return FastBinders();}
                  bool operator==(const FunctorMiddleImp &) const {return true;}
          };

          template <typename Return, typename Fun, class Parameters, class Binders> class FunctorFinalImp : public FunctorMiddleImp<Return, Parameters, Binders>
          {
              typedef typename Traits<Fun>::FastParam FastFun;
              typedef typename FunctorMiddleImp<Return, Parameters, Binders>::FastBinders FastBinders;
              typedef typename FunctorImp<Return, Parameters> Base;
              typedef typename Base::FastArgList FastArgList;
              typedef typename Base::AutoPtr AutoPtr;

              public:
                  explicit FunctorFinalImp(FastFun fun, FastBinders binders) : FunctorMiddleImp(binders), m_fun(fun) {}
                  virtual AutoPtr Clone() const {return AutoPtr(new FunctorFinalImp(*this));}
                  virtual Return operator()(FastArgList args) const {return CallFunction<Return, FastFun, FastArgList, FastBinders>(m_fun, args, FunctorMiddleImp::GetBinders());}

                  #ifdef RICE_RTTI
                  virtual bool operator==(const FunctorImp & other) const
                  {
                      if (typeid(*this) == typeid(other))
                      {
                          const FunctorFinalImp & typedOther(static_cast<const FunctorFinalImp &>(other));
                          return (m_fun == typedOther.m_fun && FunctorMiddleImp::operator==(typedOther));
                      }
                      return false;
                  }
                  #endif

              private:
                  Fun m_fun;
          };
      }

      #endif

       
    • Matthew Elkins

      Matthew Elkins - 2009-01-30

      #ifndef RICE_METHOD_H
      #define RICE_METHOD_H

      #include "ListMacros.h"

      namespace Rice
      {
          template <typename Return, typename Obj, typename Fun> class Method
          {
              public:
                  Method(Obj & obj, typename Traits<Fun>::FastParam fun) : m_obj(&obj), m_fun(fun) {}
                  bool operator==(const Method & other) const {return (m_obj == other.m_obj && m_fun == other.m_fun);}
                  bool operator!=(const Method & other) const {return !(*this == other);}

                  Return operator()() const {return (m_obj->*m_fun)();}

                  #define RICE_METHOD_OPERATOR(NUM)                                                    \             template <RICE_1_LIST##NUM##(typename T, RICE_EMPTY, RICE_COMMA)>                    \             Return operator()(RICE_2_LIST##NUM##(const T, & t, RICE_EMPTY, RICE_COMMA)) const    \             {                                                                                    \                 return (m_obj->*m_fun)(RICE_1_LIST##NUM##(t, RICE_EMPTY, RICE_COMMA));            \             }

                  RICE_MACRO_LIST29(RICE_METHOD_OPERATOR)
                  #undef RICE_METHOD_OPERATOR

              private:
                  Obj * m_obj;
                  Fun m_fun;
          };

          template <typename Return, typename Obj, typename Fun> Method<Return, Obj, Fun> Bind(Obj & obj, Fun fun) {return Method<Return, Obj, Fun>(obj, fun);}
      }

      #endif

       
    • Matthew Elkins

      Matthew Elkins - 2009-01-30

      Pasting appears to have destroyed my formatting...apologies for that, as well.
      To bind arguments, use Bind<#>(_argument_), or, in the case of reference parameters, BindVal<#>(_argument_) or BindRef<#>(_argument_), depending on what exactly is desired.  I tested it with 10 or 15 little test cases, not exhaustive testing; if there are any bugs with this please chalk it up to the experimental nature of the code (and let me know!).

      Hope this helps,
      Matt Elkins

       
    • Matthew Elkins

      Matthew Elkins - 2009-01-31

      Done.  Thanks for the link.
      -Matt

       
    • Matthew Elkins

      Matthew Elkins - 2009-01-31

      Done.  Thanks for the link.
      -Matt

       

Log in to post a comment.

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:

JavaScript is required for this form.





No, thanks