Jason Stredwick

jason.stredwick@gmail.com

Current Residence:
Bothell, WA 98011
me


Home
CV / Resume
Masters Work
WhirlingDervish
Programming
   Projects
   Various Code
     References
     Quantity/Builtin types
     Endian
     Type
     Functor
     Comm
   Additional
   Ideas
Misc. Ideas
Personal

Summary:


The Functor subsystem presented here:

Functor.tar.gz


is a extension of the Loki Functor by Andrei Alexandrescu and the Loki Library. I have taken the Functor and split it into its own entity under the namespace nFunctor. I have also split the Type headers into its own group under the namespace nType, (Type). I did this because the Functor depends on these header files. The rest of this page will give a brief overview of the components within nFunctor, a list of most of the changes made between this version and the Loki version, and the license this code falls under.

The test code for this subsystem was successfully compiled and run on Visual Studio 2005, gcc4.0 (Linux/Flavor(?)), gcc3.2(Linux/Flavor(?)), and gcc3.3.1(SunOS 5.9). Also, to compile this code all dependencies are expect to reside at the same directory level as Functor. There is a Makefile for g++ and a solution file for Visual Studio. The solution resides in Functor/Functor/Functor.sln.

Dependencies

Type

Overview

The Functor subsystem is contained within the nFunctor namespace and contains
the following components (more info provide in header files):
 -iFunctor- This provides the interface for all functors.  Currently it allows
    for up to and including fifteen parameter functors.  Essentially, the
    iFunctor provides cloning and execution.

 -GenericFunctor- GenericFunctor is generic because it can take any member
    function or callable entity in the constructor and forms a callable entity
    itself.  This class is generic because it can take a member function in
    addition to all other callable types.  However, in order to store all these
    types, it loses type information about wrapped entity.  This makes it
    difficult to compare for equivalence with other functors including itself.
    It also means that it has to create new objects, which is why it takes an
    Allocation object as a template parameter.  By default there is no special
    allocation just the normal new and delete.

 -Functor- This is an explicit version of GenericFunctor because it uses the
    type of the callable entity as part of its type.  This means that no object
    creation is necessary for storage, and comparison for equivalence is
    possible.  The downside is the potentially long type declarations of
    recursive functors.  It also means that member functions must be wrapped in
    a callable object before they can be stored in a Functor.

 -MemberFunctionWrapper- This is the callable wrapper for member functions.
    It provides the same interface as the other Functors and can be used on its
    own.  It inherits from iFunctor making it compatible with the other functor
    types.  This is also an explicit functor.

 -ReturnlessFunctor- This class is intended to wrap any callable entity
    and strip off its return value.  This class would be useful for creating
    lists of callable entities that share the same function input but don't
    care about output.  This functor is essentially, Functor, except it does
    not return anything.

 -ReturnlessMemFunWrap- This class is intended to wrap class methods
    and strip off its return value.  This class would be useful for creating
    lists of callable entities that share the same function input but don't
    care about output.  This functor is essentially, MemberFunctionWrapper,
    except it does not return anything.  I found this class helpful when
    trying to duplicate functionality from using ReturnlessFunctor because
    I would otherwise have to create a series of intermediate instances to
    hold the information to be passed to then be used by a ReturnlessFunctor.

 -BindFirst- This a functor that takes other callable entites and a fixed value.
    The fixed value is always given as the first parameter to the wrapped
    entity.  Thus, the BindFirst class must define its interface to have one
    less arguement than the entity it wraps.  This class also provides two
    helper functions for creating a new BindFirst.  The BindFirst is also an
    explicit functor.

 -Chain- This a functor that takes two callable entities and executes them
    both upon the execution of the chain.  Thus, you can create arbitrary
    chains of execution by chaining together multiple Chain objects.  This
    class is also explicit and has two helper functions to that can create
    new Chain objects.

    The concept for this class makes it essentially a static chain.  Once
    the template parameters have been defined, to swap, add, or remove
    links from the chain requires that the internal callable entity types
    match up.  Thus even though they can change, they can only change to other
    like typed entities.

 -OneToMany- This class is based on the Chain, but allows for a dynamic 
    chain.  However, to do this forces a loss of generality in that it can only
    handle functors and any class the derives for iFunctor.  With this in mind,
    it can keep a "list" of entities to execute.  It can also manipulate that
    list to add/remove/clear.  Because this class has data to manage other than
    an entity to wrap, it may need to handle threading at some point.  That is
    why it takes a StorageType as a template parameter.  That way, the
    programmer can decide how best to store and access the entities for
    execution.  Currently, the default StorageType is given in iStorageType.h
    and only handles single threaded execution.

 -ParmState- This is set up like a functor but instead of forwarding arguements
    it stores them.  It then provides a method that takes a functor to call
    using the stored data.  I have not figured out how I want to handle
    pointers.  Do I copy them or leave them the same?  The point is to keep a
    copy of the previous call, what if the data pointed to changes?  I was
    thinking of this class to be used in a delayed functor or a queuing
    functor.  A queuing functor may be something like a system resource like
    the mouse gives off its position repeatedly before the wrapped entity is
    prepared to receive it, but I want to process all of its movements.



Notes:
-Until gcc fixes their typename issues with templates such as the inability to
 use "using typename" with inherited template names and the problem with
 shadow hidden parameters, I had to leave the template arguement names as
 typedefs even though they could be inherited.  Supposedly it works on
 Visual C++, Intel C++, and Comeau.
-Handling const operator() and entities - here are some notes from iFunctor:
 * A few notes on why the operator()s are const and what that means for you.
 *  What do we see here?  If you do not have const on the operator() for the
 *    functors, you can not wrap const callable entities.  However, it seems
 *    that while const operator() allows for correct enforcement of calling
 *    const methods for const entities, it also allows for calling non-const
 *    methods on non-const entities.  I did not think that the later was valid,
 *    but apparently it is.  I am going to leave it now for two reasons.  One
 *    I would have to add duplicates of all operator() for both a const and
 *    non-const version (how to handle volatile?), and 2) I did a quick test by
 *    adding both versions to iFunctor and Functor and it will call the
 *    appropriate version for a non-const Functor, but if the Functor itself is
 *    const we are right back at square one, calling non-const object's
 *    non-const member functions.  Hopefully, someone more knowledgable than I
 *    will figure this out, otherwise I will try to come back at some point and
 *    figure it out.  What would be nice is to make the functor's operator()s
 *    const/volatile reflect the wrapped entity's const/volatile settings.
 *    However this could be tricky for callable classes because you have to
 *    look at two places: the operator() and the constness of the class itself.
-By using PtrAccessibleType, all functors can now take callable entities by
 value, reference, and pointer.  Also see next note.
-To ensure validity of a functor, all entity pointers must dereferenced during
 functor initialization to ensure a non-null value.  From there on, all
 functors assume non-null wrapped entities.  Therefore, there is the
 possibility of error due to dangling pointers, loss of scope on a given
 reference, etc.  However, I do not know a way to check for these other than
 to suggest the use of some sort of smart pointers if you are worried.
-As far as threading is concerned, I feel it is up to the entities themselves
 to ensure reentrance, not the functor.  The functor is just a wrapper.
-One issue of threading that may need to be addressed is execution order.  It is
 one thing to allow reentrance, but what happens if you have two chains each
 with a the same entity, how can you ensure the order in which entity is
 executed in both chains?  At at what level should this be taken care of?

Changes

These are most of the changes that I can remember from the Loki version:

Type
-Broke type info headers into their own subsystem structure
-I put all the type files under a new namespace nType
-Added these headers to a new subsystem structure which includes some of
 my own headers for various things.
-Added two new headers that are used by the functor classes to store their
 entities and bound/return types.  These classes are PtrAccessibleType and
 ReassignableType.

Functor
-Moved Functor into its own subsystem structure
-Broke up the Functor file into multiple files
-Changed the namespace to nFunctor
-Changed Functor to GenericFunctor, though I suppose I could change it back
 and call the new Functor class, ExplicitFunctor.
-Created a new Functor which is a more explicit version of the generic one
-Renamed the Impl stuff to iFunctor to signify that it is an interface rather
 than an implementation detail.
-Changed iFunctor to be strictly an interface
-Tried to change the inheritance of typedefs from iFunctor and iFunctorBase.
 However, it is mostly the same because I had to change it back when I
 discovered that gcc does not handle using typename correctly.  I also had to
 change some template parameter names because gcc does not handle inheriting
 template names that are the same as the derived class's version.
-Removed SmallObjectAllocation from GenericFunctor and added a generic
 Allocation template parameter instead.  You can just pass in SmallObjectAlloc
 if you want.  The allocation defaults to an empty class.
-Moved comparisons out of the functor classes and made them non-member,
 non-friend functions.
-Removed the RTTI stuff.  All functors are compariable for equivalence except
 iFunctors and GenericFunctors.  If we want to add RTTI comparisons for the
 functor types, it would be best if they were handled like the other
 comparisons, as non-member, non-friend functions.  I may add them in later
 anyways, but just hadn't decided how I wanted to do it yet.  The same goes
 for reverse cloning through iFunctor.
-Changed all functors so they allow value, reference, and pointer versions of
 callable entities.
-Pointer callable entities will throw a BadCallableEntity exception if the
 pointer is null.
-Changed the methods for accessing the interface for all functors to casting,
 or two get methods, one for a pointer and one for a reference.
-Added some comments
-Added a test function for all the functors
-Kept BinderFirst and Chainer in line with the other functors.  They are now
 solely dependent on iFunctor.
-Modified the BindFirst and Chain functions
-Swapped the names of the Chainer class and Chain functions
-Functor is similar to FunctionHandler class
-MemberFunctionWrapper is based on the MemFunHandler class
-Added ParmState which acts like a functor but stores the data internally, then
 provides an execution method that takes a callable entity and executes it with
 the saved data.  This is essentially a work in progress.
-Added OneToMany functor, which is similar to Chain but allows for dynamic
 chaining of callable entities.  This class comes with the iStorageType.h
 supporting file.  I am not sure if I want to keep iStorageType.h here or move
 it to another subsystem.  Also, I don't like iStorageType and will probably
 change it in the near future.
-Added ReturnlessMemFunWrap
-I started calling the TypeList versions of things recursive and Seq versions
 linear, in the comments.
-Added const to the operator()s to enable const entities and const methods.
 See documentation (iFunctor comments or FunctorInfo.txt) for more details.
-Store data differently

License

////////////////////////////////////////////////////////////////////////////////
// The Loki Library
// Copyright (c) 2001 by Andrei Alexandrescu
// This code accompanies the book:
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design 
//     Patterns Applied". Copyright (c) 2001. Addison-Wesley.
// Permission to use, copy, modify, distribute and sell this software for any 
//     purpose is hereby granted without fee, provided that the above copyright 
//     notice appear in all copies and that both that copyright notice and this 
//     permission notice appear in supporting documentation.
// The author or Addison-Wesley Longman make no representations about the 
//     suitability of this software for any purpose. It is provided "as is" 
//     without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////