I've been learning about BOOST Spirit, a C++ expression based compiler generator. One of the examples is for a Roman Numeral parser. This contained the following interesting code for pre-loading a symbol table:
struct ones_ : qi::symbols<char, unsigned>
{
ones_()
{
add
("I" , 1)
("II" , 2)
("III" , 3)
("IV" , 4)
("V" , 5)
("VI" , 6)
("VII" , 7)
("VIII" , 8)
("IX" , 9)
;
}
} ones;
So,
struct ones_
is a new class definition.ones_()
is the constructor.- The call to
add("I", 1)
is a call to the member function add
associating the string "I
" with the value 1
by adding them to the symbol table.
There's nothing particularly strange there. However, the continuation, i.e. add()()()()()
... looked a little odd and puzzled me for a minute or so. Then I realized add()
must be returning *this
and the other ()
s were invoking the parenthesis operator, i.e. in this case, ones_& operator()(const char*, const int);
.
Following this little revelation, to confirm the theory, I constructed the following program which sums the numbers 1-6, printing 21.
#include <iostream>
class Func
{
private:
int m_sum;
public:
Func(const int n) : m_sum(n) { }
const int Sum() const { return m_sum; }
Func& operator()(const int n)
{
m_sum += n;
return *this;
}
static Func add(int n) { return Func(n); }
};
int main()
{
std::cout << Func::add(1)(2)(3)(4)(5)(6).Sum() << std::endl;
}
All that's needed is a seed function, in this case add()
which returns *this
followed by operator()()
. It would work fine without the named seed function using just operator()()
but then it would lose a little meaning.
This isn't really that helpful and in most circumstances probably constitutes obfuscated code. However, it's certainly cute and where overloading is done fully and with meaning of which Spirit is a case in point, then it becomes an effective and usable syntax.
As Fluent Programming seems to be on rise, this is another demonstration of it within C++, just like iostreams. The added Syntactical Sugar provided by C++'s Functor mechanism makes for Fluent Functors.