Monday, September 3, 2007

Version 0.8.1.0 out

After some minor changes, mostly in the documentation area, released as 0.8.0.x, there is a more significant change in 0.8.1.0, adding a "pointer use policy". A named functor is a very simple object; it is just a wrapper that uses some internal "smart pointer" to reference an object of a more complex type that actually does the job for the named functor. Until now these "smart pointers" were always "shared", using a reference counter; so when a named pointer was assigned to another, they used internally the same copy of the "worker" object.

That is fine until you want to use a copy of a named functor among multiple threads. That may work incorrectly because there is no synchronization of the smart pointer's functions, so the reference counter might be changed by one thread while another is trying to do the same, leaving the counter in an inconsistent state. Another potential issue was that the same sharing policy was used for user-created functors derived from QuickFunctor's FBase; this becomes an issue when these classes have modifiable state and non-const methods. If a single "worker" object is used that is shared by two named functors, changing one of the named functors will effectively cause the other one to change too.

Well, now the "shared pointers" are still used by default, but there's a choice to use "cloned pointers". They create copies of the "worker" objects when calling constructors or assignments.

It is also possible for users to provide their own implementations for smart pointers, which can be used along with the predefined ones.

For more details see the main project page at SourceForge

Saturday, August 18, 2007

Version 0.8.0.0 out of the door

After some frustrations with what is provided by the Standard Library, I started to develop QuickFunctor with the declared purpose to create a library that allows its users to do pretty much anything that is reasonable to do with functors (aka "function objects"), and do it as easily and as efficiently as possible.

Many "idea leaders" in the C++ community (Bjarne Stroustrup, Scott Meyers, Herb Sutter, Daveed Vandevoorde, Nicolai Josuttis among them) advocate using functors, and I find their arguments persuasive. The standard library provides an implementation for functors, in the <functional> header, but from my point of view it has some drawbacks and limitations, which were significant enough to make me decide to write my own QuickFunctor, which I think has several advantages:

  1. Functors can be combined in expressions (arithmetic, boolean, string, ...), using most C++ operators. Expressions of numerical and string types are handled directly, and user types can easily be accommodated, if needed, including numeric user types (like Fraction) that can be combined in expressions with standard types (like int).

  2. Constructors for functors take a more diverse set of parameters. You can build a functor from pretty much anything.

  3. It can deal with functors with 3 or more parameters.

  4. A more consistent naming scheme.

  5. An extensive set of operations that can be applied to existing functors to create new functors. These operations include mathematical composition, various conversions, binding, parameter substitution, permutations and casting.

  6. The possibility of storing functors in variables with simple types. Functor<int, double, char> is a type that can store any functor that takes a double and a char as its parameters and returns an int.


These arguments also apply to some extent to Boost and TR1, which have some improvements over the current standard, but don't go far enough. The Loki library has its own functors but they can't do everything QuickFunctor does.

Depending on how advanced you are with C++, chances are that you'll find some new ideas for C++ metatemplate programming (popularized by Andrei Alexandrescu) and general C++ programming techniques, for those willing to look at the code. While some techniques that I use are well known, others have been developed by me. I'm sure that among them there are some that have been discovered independently by other people, but it's also possible that some of them are actually new.

One example would be a technique that allows to effectively have 2 template functions "template <class T> void f(T x)", which exist simultaneously in the same namespace, one of them called for some kind of arguments and the other for other kinds. Simply having in a source file the code "template <class T> void f(T) {}; template <class T> void f(T) {};" generates a compiler error, because of a duplicate definition of f. Yet, I introduce a technique that allows something that behaves like this to work. Probably somebody else thought of it before, but there are many other things, some of which might be new.

I wrote this library for myself, but by making it public I hope other people will benefit from my efforts and perhaps help me improve it.

Anyway, after lots of small tweaks and complete redesigns I finally managed to pack together a functional version of the library, together with documentation and examples, I decided to call it 0.8.0.0 and I'm glad that it's out. While it's a beta and there are some "open issues", there are no bugs that I know of. The library can be downloaded from SourceForge. Since the SourceForge forums require users to log in, I decided to create this blog where I can post news about QuickFunctor and also get some feedback from people who don't want to log in.

Enjoy
 
FREE hit counter and Internet traffic statistics from freestats.com