Boost C++ & Operator Overloading

As you may or may not know already, I recently started a new job.  The new company makes a lot more heavy-duty use of C++ than the previous one did.  Among the C++ code is the 3rd party Boost C++ library.  I had peripherally heard of Boost before, but had never looked too deeply at it.  It is a set of standard cross-platform C++ classes that perform a variety of useful operations.  You can think of it like an addition to the Standard Template Library (STL).  In fact, they are trying to get some of their code accepted as future C++ standards.

There are two classes in Boost that are used frequently in our code: format and path.  I like them and find them useful, but a small detail of their implementation just rubs me the wrong way.  Before I get into that detail, let me first discuss their utility.  Programmers often have to format strings.  In C, the way to do this is similar to:

sprintf(buffer, "The answer to %s is %d", "your question", 42);

You had better hope that “buffer” is big enough to hold the answer, though.  You could dynamically allocate the buffer (and remember to free it later).  You can use snprintf() and worry about the null-terminator if the buffer is too small.  But any way you do it, it’s going to take a few lines of code, might not be memory efficient, and probably isn’t as clean as it should be.

The regular C++ way of performing this operation uses a class to worry about the details of buffer size, string length, and releasing the buffer.  For example:

std::ostringstream buffer << "The answer to " << "your question" << " is " << 42;

This sort of works, but gets ugly if you have lots of variables interspersed with static text.  It also kills any efforts at internationalization.

The Boost way of doing this is more like the C way, but without the buffer size worries:

std::string buffer = str(format("The answer to %s is %d") % "your question" % 42);

It is even less crash-prone than the C sprintf().  If you were to feed it only one argument, but have two or more placeholders in your format string, Boost would be fine, but sprintf() may choke, include garbage, or crash.  With Boost, you can even get more fancy (with better i18n compliance) by using positional arguments:

std::string buffer = str(format("The answer to %2% is %1%") % 42 % "your question");

The percents act sort of like the Python formatting operator:

buffer = “The answer to %s is %d” % {“your question”, 42};

The Boost object for working with paths uses a similar trick, only instead of the percent operator, it’s the slash operator.  You can do something like this:

path myPath = "/home/brian";
myPath = myPath / "Pictures";
myPath /= "photo.jpg";

And in the end myPath.string() holds the text “/home/brian/pictures/photo.png”.  It gets the slashes and backslashes correct for Unix versus Windows and has all sorts OS-agnostic helper functions for creating paths, deleting files, and whatnot.

As much as I like these classes and enjoy their ease of use, there is one minor thing that rubs me the wrong way, as I mentioned above.  Specifically: the “clever” way they’ve overloaded the percent and slash operators.  I was taught long, long ago that although you can overload standard operators in C++ it’s a bad, bad thing to be too clever in changing their semantic meaning.  The operator+() function should always perform some sort of addition (be it summation or concatenation).  Similarly, operator/() should divide or do something akin to division.  Operator%() should be modulus (the remainder after dividing).  You can overload them to do something special for your class related to the original meaning (adding complex numbers, cross-multiplying matrices), but you shouldn’t go too out-of-bounds with their meaning.

I could have sworn that I read this in the Bjarne Stroustrup C++ book or one of the other top-rated C++ books, but skimming my digital copies to find a specific reference quotation to cite turned up nothing.

Do I find the format and path classes incredibly useful?  Yes!  Do I find their operator overloading a minor annoyance?  Yes!  Is it annoying enough to prevent me from using those classes?  No!  I find the Boost implementation of the slash and percent a little too outside the box from what I’m used to, but I’ll go ahead and keep using them and will probably get used to it in time.

Posted in: Code Work

Published by

Brian Enigma

Brian Enigma is a Portlander, manipulator of atoms & bits, minor-league blogger, and all-around great guy. He typically writes about the interesting “maker” projects he's working on, but sometimes veers off into puzzles, software, games, local news, and current events.

2 thoughts on “Boost C++ & Operator Overloading”

  1. I don’t see why you are so bothered by these untraditional operator overloads. the standard iostreams do the same thing, consiter for example:
    std::cout << "hello, world!" << std::endl;
    That is an overloaded bitshift operator. The '<<' operator in this example certainly doesn't have the same semantic meaning as bitshift, but you don't give it a second thought, because you use it all the time.

    1. I’m ready to admit that it is entirely arbitrary. It actually took a bit for me to get used to “<<" for I/O (I always fell back to good ol' printf and syslog). It's just one of those things I learned in the past (either in College or some other class) and now have to "unlearn." The more I use boost::format, the more I like it (as opposed to building up a buffer and snprintf'ing into it, then ensuring it is terminated correctly).

Leave a Reply

Your email address will not be published. Required fields are marked *