To C or not to C
One of the pitch lines of the Drizzle project in their rewriting of MySQL code is to rely on standard libraries and make it a full blown C++ project, implying that there's no reason to hold back.
When we started Galera we explicitly decided to do it in C. We didn't have a confidence that libstdc++ was mature enough and expected to have all sorts of problems with it.
Time passed. C++ kept on luring us into its sweet trap. Let's face it: C++ is a far more expressive language than C. Starting from the ability to have constant structure members to exceptions to automatic resource management. Heck, references alone is a reason good enough to switch to C++. And then go STL and boost which drastically speed up prototyping. And finally there are encouraging examples, like that of Drizzle. Hell, they even use it in aerospace: "Joint Strike Fighter Air Vehicle C++ Coding Standards". You can't go wrong with that, can you?
And so there were some weak of heart, who succumbed to the call. At first it went well, but then... you're right - we hit the legendary problems. It is mostly about compilation on different Linux distros (mind you - not different platforms!), but it just shows how mature that 25+ year old language is.
To begin with we don't imagine ourselves to be smarter than GCC, so we use -Werror. We want our code to follow the best practices, so we use -Weffc++. And then you have it:
(CentOS 5.0, gcc-4.1.1, boost-1.33.1):
/usr/include/boost/pending/property.hpp:25: warning: 'boost::property
Offending code piece:
struct property : public Base {
typedef Base next_type;
typedef Tag tag_type;
typedef T value_type;
property() { } // offending line
property(const T& v) : m_value(v) { }
property(const T& v, const Base& b) : Base(b), m_value(v) { }
// copy constructor and assignment operator will be generated by compiler
T m_value;
};
One might say, well, that's their style! Apparently not, cause when you check the same code in boost-1.34 in Ubuntu 8.04, you'll see:
struct property : public Base {
typedef Base next_type;
typedef Tag tag_type;
typedef T value_type;
#if BOOST_WORKAROUND (__GNUC__, < 3)
property() { }
#else
property() : m_value() { }
#endif
property(const T& v) : m_value(v) { }
property(const T& v, const Base& b) : Base(b), m_value(v) { }
// copy constructor and assignment operator will be generated by compiler
T m_value;
};
From the looks of it there were some points where both GCC developers and boost developers didn't know what they were doing. Boost developers seemed to get epiphany just between 1.33 and 1.34 releases, but only partially - most of boost code is still guilty of not initializing members in the initialization lists. Same goes for GCC folks: g++-4.2.4 just doesn't emit warnings where g++-4.1.1 did. Isn't that just what we expect from a well researched problem field?
And after you get to read the following in the libstdc++ FAQ:
Many warnings are emitted when -Weffc++ is used. Making libstdc++ -Weffc++-clean is not a goal of the project, for a few reasons. Mainly, that option tries to enforce object-oriented programming, while the Standard Library isn't necessarily trying to be OO.
you know that you happened to land the right company. Who needs OO? I hope OO is not the reason you choose C++ over C? Wait, it can't be! You're into OO too!? (Truth be told, we have not seen any such warnings from libstdc++ however.)
And then someone reports:
In file included from pollpp.cpp:6:
../../common/include/galeracomm/fifo.hpp: In constructor ‘Fifo::Fifo()’:
../../common/include/galeracomm/fifo.hpp:33: error: ‘numeric_limits’ is not a member of ‘std’
How come in my Ubuntu installation it is and in another it is not? It might be a mess on the part of the guy who reported it, but one should not be able to mess so much. After all we're talking about std here. It stands for 'standard', does it not?
And it seems that even Drizzle, the troubadour of C++ he is, didn't escape that fate as well. From the drizzle-discuss mailing list:
# To: Monty.Taylor@xxxxxxx
# Subject: [Drizzle-discuss] Getting protobufs 2.1 to compile on SPARC
# From: Lee Bieber
# Date: Fri, 14 Aug 2009 15:41:37 -0700
Hi Monty,
The upcoming merge to trunk will require protobuf 2.1 so I am trying to compile protobuf 2.1 on SPARC. I believe you had a patch for this, but I couldn't find it.
Thanks, Lee
C" void(*)() in call to pthread_once(_once*, extern "C" void(*)()) is being passed void(*)(). "./google/protobuf/stubs/once.h", line 114: Warning (Anachronism): Formal argument 2 of type extern "C" void(*)() in call to pthread_once(_once*, extern "C" void(*)()) is being passed void(*)(). "./google/protobuf/repeated_field.cc", line 52: Error: google::protobuf::RepeatedPtrField
So, you need a patch to compile that on SPARC. How come it compiles elsewhere?
What made this mess possible? I think the main honor goes to C++ standards committee. It appears that they were too much concerned with preserving backward compatibility with previous C and C++ standards. And you know what? A standard CANNOT BE BACKWARD COMPATIBLE! The whole point of a standard is to be as specific about things as possible, not to allow multiple interpretations and implementations. That's what they mean saying "there is a standard way of doing this". Now, how come I can forgo initialization of class members at my discretion? What is a point of allowing to do so if you still have to initialize constants? It is exactly such provisions that allow people to write incompatible code and compilers. Now, I'm not against backward compatibility, but it has its time and place called "compiler". It is the compiler that can be backward compatible by supporting outdated standards, not the standard by allowing obsolete ways of doing things.
But what is most upsetting, is that this reflects the overall zeitgeist that ensured the demise of initiatives like Ada95. Backward compatibility to allow people to work in old ways, carrying over bad habits and obsolete approaches, in other words: stay backward. Why C99 still allows 'if (x = y) {}' when almost every compiler complains about it? Why C++ still is so sloppy about throws() directive, making it almost useless? Why Java syntax was taken from C which is known to be notoriously poor? Why have they chosen C++ instead of Ada to program aircraft (and have to come up with 140 pages of "coding standards" because C++ standard just does not cut it)?
The bottom-line? Well, there is no turning back and eventually all Galera modules will be rewritten in C++, for its a really sweet language despite the failings of the standards committee. Even though it means a neverending struggle with the Backward Zeitgeist.
- alex's blog
- Login or register to post comments
