An ode to the cast operator

Working on a project that is written 90% in python that uses JSON for its configuration, I had to parse the python generated JSON in C++. Not a problem, C++ boost has an excellent and usable library that has JSON support, the Boost Property Tree library. Unfortunately however the target platform comes with the 1.40 version of the boost library, and guess what, the boost property tree library became first available in the 1.41 version. Off to look for a different JSON library that is available as a standard package for the target platform. After searching the pachaging system of my target platform I found it comes with JSON-Glib.

First I started out being happy about the fact that I found an alternative JSON library for my project, but my joy quickly resided when I realized it was a C++ library with one of those API’s. Untill we get the rout node of our JSON document all looks fine, but once we have our first JsonNode while expecting to get a transparent API that maps effortlessly to the base C++ types, we end up being exposed to all kinds of JSON-Glib classes, and some classes from the core Gnome library.

Having written some of   those libraries myself, I know its easy to start believing in the merits of your own project internal type system, thinking nothing about exposing it to your library users.There are however a few useful tricks you can use with relatively little effort to decouple the knowledge of your library internal type system from the need of your library users to be exposed to that knowledge.

  • Cast operators
  • Subscript operators
  • Value semantic smart-pointer wrappers.

When designing an API for a library using these 3 tools, it is possible to greatly decrease the learning curve for using your library. You provide syntactic sugar that hides much of your internal type system from the part of your user base that isn’t that interested in learning about your no-doubt brilliantly designed library type hierarchy.

The cast operator

The most interesting of the 3 tools is the C++ cast operator. Adding a cast operator to a type allows to simply assign an object class that can validly be represented as a base type, for example an std::string, to a variable of that type. Yes, its just syntactic sugar, but its syntactic sugar that allows your library user to not learn about the internals of your library. We shall come back to the cast operator later, but lets start off by an example of an API class that uses cast operators. The following is part of a wrapper library for JSON-Glib that I am currently working on:

typedef enum {FLOAT,INTEGER,STRING,BOOL,NULLVAL} scalartype;

class AbstractScalar {

public:

virtual ~AbstractScalar(){}

virtual jsonme::scalartype type()=0;

virtual operator long double()=0;

virtual operator long long()=0;

virtual operator std::string()=0;

virtual operator bool()=0;

virtual bool isNull()=0;  };

 }

Subscript operator

An other piece of powerful syntactic sugar that is provided by languages like C++ and Python that support operator overloading is the subscript operator. For our JSON-Glib wrapper for example the subscript operator could be used both for accessing JSON object members by key, or for accessing JSON  aray members by index.  Again an excerpt from the wrapper library I’m working on:

typedef enum {OBJECT,ARRAY,SCALAR} nodetype;

class Node;

class AbstractNode {

public:

virtual ~AbstractNode(){}

virtual jsonme::nodetype type()=0;

virtual Node operator[](std::string name)=0;

virtual size_t size()=0;

virtual Node operator[](size_t index)=0;

virtual operator Scalar()=0;

};

If we combine this with the previously discussed cast operator, our JSON wrapper library could in theory be used as follows:

std::string firsthostname= rootnode[0][“host”][“name”][0];

As should be clear from this, the user should potentialy have verry litle knowledge if any about the types the API is composed with.

Value semantic smart-pointer wrappers.

A third piece of syntactic sugar that may not be directly obvious is the use of value semantic smart-pointer wrappers in our API.  As a rule, a library should not burden the users of that library with the issue of having to think about resource management. C++ provides the concept of smart pointers to help with correctly managing resources. Exposing and forcing the use of smart pointers can be a proper choice, for example returning an auto_ptr or a unique_ptr from a factory is much better than returning a raw pointer. In the library wrapper we are discussing here however, it may be much more suitable to completely hide the usage of smart pointers (that have pointer semantics) by providing a value semantics wrapper for the smart pointer.

class Node: public AbstractNode {

boost::shared_ptr<AbstractNode> mNode;

public:

Node(AbstractNode *node):mNode(node){}

~Node(){ delete mNode();}

jsonme::nodetype type(){ return mNode->type();}

Node operator[](std::string name) { return (*mNode)[name];}

size_t size() { return mNode->size();}

Node operator[](size_t index) { return (*mNode)[index];}

operator Scalar() { return (*mNode);}

};

conclusion

I hope that with the above examples I’ve shown how a adding a little bit of syntactic sugar to your library API can make a lot of sense when you want to spare your library users from a relatively steap learning curve. Although I have myself often been to lazy and presumptuous with respect to my own libraries and their type hierarchy to be thorough and sufficiently frequent in the usage of these constructs in my API’s, but running into JSON-Glib while only needing to parse a config file made me aware once more of the user perspective of those API’s. Remember that if your library is any good it will have more users than it has developers. Users that will be grateful for a reduced learning curve. And if its a library for a tiny market, than you may possibly still increase the number of potential users by adding these 3 ingredients to your API. I like all 3 of the syntactic sugar components described above, but to me the C++ cast operator is their absolute champion.

Advertisements

One response to “An ode to the cast operator

  1. For those interested in real code, I’ve put some half done code up on github. https://github.com/pibara/jsonme–

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s