Stroustrup and the C++ community are right, which proves them wrong.

When Bjarnes Stroustroup designed the C++ class concept, he made the default accessibility “private”, so as to encourage encapsulation and data hiding.

That’s as far as he went, immediately violating his own principle.

C++ makes it very difficult to provide non-invasive prototypes. That is, if you have a module “foo.cpp” and you want to advertise an API for it, you’re going to have to either manually prototype all of the types that it invokes, or #include stuff.

The worst-case hellish nightmare is if you go near the STL, say for “std::string”.

Nobody ever prototypes std::string, we all just revert to #include <string>. Even when all we’re doing is describing references.

Consider the following, trivial program:

#if USE_STRING == 0
void foo(const char* const bar);
#include <string>
void foo(const std::string& bar);

int main(int argc, const char* argv[]) { return 1; }

Lets see how it compiles:

osmith@dev1:~$ export USE_STRING=0 ; time ( X=100 ; while [ $X -gt 0 ]; do touch test.cpp ; make -ks ; X=$(expr $X – 1); done )
real 0m8.341s
user 0m4.448s
sys 0m2.072s

osmith@dev1:~$ export USE_STRING=1 ; time ( X=100 ; while [ $X -gt 0 ]; do touch test.cpp ; make -ks ; X=$(expr $X – 1); done )
real 0m34.031s
user 0m28.642s
sys 0m3.724s

osmith@dev1:~/tmp$ export USE_STRING=0 ; time ( X=1000 ; while [ $X -gt 0 ]; do touch test.cpp ; make -ks ; X=$(expr $X – 1); done )
real 1m23.439s
user 0m43.799s
sys 0m21.597s

osmith@dev1:~/tmp$ export USE_STRING=1 ; time ( X=1000 ; while [ $X -gt 0 ]; do touch test.cpp ; make -ks ; X=$(expr $X – 1); done )
real 5m40.009s
user 4m45.022s
sys 0m37.930s

ARGH! That’s a hell of a lot of CPU wastage just to be able to say “function references a string”.

26 real seconds every 100 compilation units, FOUR minutes per 1000! Just for std::string?!?

Then Java came along and extended Stroustrups notion a logical step further and introduced the interface concept.

An interface only describes function members, it has no size or data structure. More importantly, it describes an “has a” relationship rather than an “is a” relationship of normal inheritance, which allows compilers and compiler designers to do interesting, useful and time saving things.

And all it does is logically follow the separation of concerns Bjarnes was so seemingly concerned with: If I am only able to see “class Foo” in terms of its public members, and if non of its data structure is included, then why the hell do we have to define all of the structure mahoney up front?

Some would argue that the solution is to use multiple inheritance and the pimpl idiom. That’s great, except that the pimpl concept introduces dubious optimization factors, such as the root object and its all important implementation being separated in memory. YAY! Thanks for screwing up my cache lines.

But they also get proven wrong by the STL, which is a hellish nightmare of spaghetti dependencies precisely because they are hellbent on proving “you can do it without interfaces”. Yes, you’re right, you can, as long as you want to stipulate “in a piss poor way”.

Because Java beat them to it, though, the C++ folks aren’t going to let it happen.

Which is just stupid. Bjarnes Stroustrup needs to accept his place as the grandpa of “interface” and add it to C++ already.




just have to love NIMBYism – I did laugh when the java folks introduced lambda functions and mappings a few years ago (something I remember using in LPC many, many moons ago)

I just added a USE_STRING=2 case,

#if USE_STRING == 0
	void foo(const char* const bar);
#elif USE_STRING == 1
	#include <string>
	void foo(const std::string& bar);
#elif USE_STRING == 2
	#include <string>
	#include <vector>
	#include <map>
	#include <algorithm>
	void foo(void);	// NOTE: I don't even mention any of the types!

int main(int argc, const char* argv[]) { return 1; }

And then ran 1000 iterations on that, forgot about it, went off and did other things (but not on that machine), came back and noticed how long it had taken and almost barfed… This is stupid!

osmith@dev1:~/tmp$ export USE_STRING=2 ; time ( X=1000 ; while [ $X -gt 0 ]; do touch test.cpp ; make -ks ; X=$(expr $X - 1); done )
real    12m5.680s
user    10m47.220s
sys     1m0.960s

Remember, build time for 1000 units without including the STL: real 1m23.439s

Meh, just use a precompiled header and throw all the standard stuff in there.

The one area where C++’s age shows most clearly is in compilation: While newer languages are defining all sorts of modules and environments as ways of splitting up code, C++ is still just “Nope, it’s just text” and hasn’t even touched the issue of how it’s compiled. While it’s kind of a good thing that the C++ standard hasn’t stuck its nose too far outside of just being a language, there are times where just admitting that the compilation process is pretty much universal at this point would be nice.

@victarus Doesn’t make the bloat go away, it just increases it, and the result of throwing string, vector, map, set, list, dequeue and algorithm all into your bootstrap include is even harder on a PCH than it is on plain includes. Yes, it’s faster than not having a PCH, but you only have to include a few bits of the standard library and you’re slower than not using a pch in the first place :(

Leave a Reply

Name and email address are required. Your email address will not be published.

Fill in your details below or click an icon to log in: Logo

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

Google photo

You are commenting using your Google 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 )

Connecting to %s

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <pre> <q cite=""> <s> <strike> <strong> 

%d bloggers like this: