Saturday, October 3, 2009

From Frivolity, Functionality Follows

Custom operator library for C++

Several months ago a friend of mine came up with a way to make valid C++ out of ^_^. Using the code in that link, foo ^_^ bar is equivalent to assert(foo != bar) (as long as foo & bar are implicitly convertible to ints, of course).

The topic came up again the day before yesterday, and I decided to try implementing it myself (having entirely forgotten what the original code looked like). My version used a template so that the operator could be applied to any type. When I tested it using an assertion instead of an exception, I stumbled upon my compiler’s ability to optimize the entire operation away when compiled in release mode.

After playing around with the template design trying to implement other operators, I realized the overall design was highly susceptible to generalization. So began a 48-hour mission to put together an easy-to-use library for creating custom operators. The result?

IdOp*, short for Identifier Operator, provides a few simple macros (at least on the front-end) to generate all the necessary templates for a wide variety of operator configurations. Here’s a small sample to whet your appetite. Further details are available in the source code.

// SIMPLE
//   x ^__- y <=> x / y
IDOP_CREATE_RIGHT_HANDED(^, __, -, Examples::Quotient)

// COMPLEX
IDOP_CREATE( _ ,
    IDOP_LEFT_HANDED( - ,
        // x -_^ y <=> x + y
        IDOP_OPERATION(^, Examples::Sum)
    )
    IDOP_LEFT_HANDED( > ,
        // x >_> y <=> abs(x - y)
        IDOP_OPERATION(>, Examples::Difference) 
        // x >_< y <=> if (x != y) throw
        IDOP_OPERATION_RET(<, Examples::ThrowNotEqual, void)
    )
    IDOP_RIGHT_HANDED( - ,
        //  x ^_- y <=> assert(x != y)
        IDOP_OPERATION_RET(^, Examples::AssertNotEqual, void)
        //  x |_- y <=> x * y
        IDOP_OPERATION(|, Examples::Product)
    )
)

The only feature I feel it’s missing is the ability to modify one or both of the operands. When I was originally designing the templates, I threw const around like crazy to make sure I didn’t miss out on any static evaluation. Now that I have the code generation architecture finished, it should be a breeze to add in mutable operands.

Then come the joys of documentation…


* I've been pronouncing it EYE-dee-ahp (sounds sort of like giddyup) or EYE-dahp