Domain: moderncppdesign.com
Stories and comments across the archive that link to moderncppdesign.com.
Comments · 16
-
Re:a 'few' rough edges
C++ is capable of much much more than just object-orientated programming. Look at all of the template craziness going on by Alexandrescu for generic programming. See the Boost Lambda library for some functional programming examples. Heck, even wikipedia says "C++ is designed to directly and comprehensively support multiple programming styles (procedural programming, data abstraction, object-oriented programming, and generic programming)" [Ref. And it does *all* of this without any sort of major performance detriment.
-
A second wave for C++
I won't argue the relative merits of C++ to other languages. For many organizations, switching from C++ (regardless of whether it would make things easier) is often not an option, and not considered as an option. I will also not argue whether that is bad.
The fact is, there's a huge C++ user and code base out there, and if they are going to stick with C++, there's exciting stuff coming.
I feel that C++ is having its second coming, primarily due to developments like the boost library and the Modern C++ Design book.
For example, I've been using a combination of boost::function and boost::bind to make powerful, flexible callbacks like nobody's business. Finally, there's a function "pointer" that can work with both freestanding functions, member functions and function objects, and finally there's an easy way to delay calling functions and use closures, respectively. (Also see boost::lambda).
Sure, almost all of this has been possible one way or the other (the flexible callback has been typically implemented via function ptr and void ptr argument, C-style), but it's very refreshing to actually have the code say what you mean: "I want to delay calling this function", or "this callback doesn't give a crap whether the function you're giving it is a member function or not".
Then there are smart pointers, which have easier-to-follow, clearer semantics, and can be used in STL containers and such. No more using easy-to-shoot-yourself-in-foot auto_ptr. It's been possible to write large chunks of code that have multiple "new" statements, but have no "delete" statements, all while maintaining exact control over the memory allocation.
Of course there's more... Maybe it's stuff that LISP/Scheme programmers have been using for ages, but the key difference is I can now apply tools in production commercial C++ code, during my everyday work. I no longer sit and say: "oh, crap, I could really use a closure here." I just do it.
A big problem is that the new features require greater understanding of the language and thus better training of the run-of-the-mill C++ developer. Many C++ developers I encounter do not have the sufficient understanding of these tools, and of the language. We should strive to educate our fellow developers, ... For Great Code! -
Re:What if I program in C++ ?
I did XP in extreme C++ for about a year (by extreme C++, I mean boostified, Alexandrescu'd C++). We used CppUnit for our test framework.
I'm not especially satisfied with the currently available C++ unit testing frameworks. CppUnit and Boost's both have trade-offs. I suspect they'll both get better, though.
The Ant-Contrib project's cc task works pretty well, in my limited experience. I was playing around with it just this weekend. I've yet to set up a tinderbox build process, but I don't see why this wouldn't be easy with either Cruise Control or good ol' cron.
In my mind, the two biggest hurdles with doing XP in C++ are build speed and developer prejudice. You can tackle build speed with a combination of ccache, distcc, good programming principles, and cash. Tackling developer prejudice is harder. A lot of C++ programmers like to write low-level, unsafe, old school C++ code. Modern C++ mostly lets you discard unsafe coding practices without sacrificing efficiency. Whether you can convince an old C++ programmer of this is another matter; it depends on the person. I've had decent success taking Java programmers and teaching them modern C++ via pair programming.
Using Boost helps, indirectly. You write safer code, which gives you a faster development cycle. All in all, I think the basic tools are there. It might be a little harder to get fancy lava lamp integration going with C++, but there's no reason why you can't have a good build process. It's just that a lot of C++ projects haven't evolved (I think this is due, in part, to the fact that the C++ community is late to the internet; a lot of C++ programmers just don't know what's, out there.
cheers,
Jon -
Re:Hungarian Notation
How embarrassing for "most Open Source projects". All the expert-level C++ books (Alexandrescu for example) use only a trailing underscore for data members, and Sun's sample Java code uses no prefix at all. "m_" is pretty much unique to M$ and their victims.
-
Book recommendations
I thought about coming up with a syllabus for myself of C, Haskell, LISP and Perl (which just evades me....)
I'd like to strongly recommend some books. The first is Modern C++ Design by Andrei Alexandrescu. The second is On Lisp by Paul Graham. In conjunction with that, you will need an introductory text on Lisp if you don't already know it and a good book on C++ templates. While I don't know what the best Lisp text currently in print is, I'd be willing to give Graham's ANSI Common Lisp a try on the strength of his other book. And C++ Templates: A Complete Guide by Vandevoorde and Josuttis illuminates a lot of dark corners in templates and explains some new features.
In the end, the goal is to understand how many times Graham and Alexandrescu are talking about the same things using very different languages. C++ templates are in many important ways a compile-time, functional macro language on top of C++ that implement many of the features of Lisp macros. For what it's worth, Bruce Eckel has mentioned this generic programming link in the context of discussing Java generics. -
Lisp, Java and C++
There's a pair of books that make interesting reading together. One is Paul Graham's On Lisp. Whatever you may think of his statements against other languages, he knows Lisp and he does an excellent job of explaining how to use it well. I didn't understand how to use Lisp macros effectively until I read it, or why to use them.
Shortly after reading it, I read Modern C++ Design by Andrei Alexandrescu. Reading that, I started to understand some of the power of generic programming. If you understand when these two books are explaining two very different implementations of the same things, then you have grasped the essence of some very powerful techniques.
Frankly, generic programming is one place where Java is still definitely lagging. Fortunately, there is currently an effort to fix that.
Lisp's greatest strength is also its greatest weakness. The language eschews nearly all syntax. All structure within a program that would be expressed syntactically in other languages consists of levels of parentheses and order of arguments to various functions, macros and special forms. There is great power in this. It means that what you add to the language fits in seemlessly. That is the point of Graham's title for his book. Read the first chapter for his explanation.
Unfortunately, this very scarcity of imposed syntax puts a burden on the programmer to format for clarity and to learn to read in a language where some of the familiar signposts simply are not present. That task is certainly possible, but it puts many people off. -
Re:Yea. Ok. Perl do it, too.
Perl, cpp, m4, C++, and other code-generation systems do TEXT substitution/rewriting.
There is a lot more going on here (for instance) than text-substitution. The syntax for C++ templates may make LISP's seem downright pleasant, even for a LISP-hater, and some of the techniques border on language abuse, but it forms a full-blown compile-time functional programming language that integrates fulling into the C++ type and class mechanism. The Boost library collection is full of such metaprogramming, such as this.
-Ed
-
Microsoft's IDEs? You have GOT to be kiddingUsing Microsoft's IDEs - I have VC++ both 6 and 7 - is like pounding nails with my fists.
Have you used Metrowerks Codewarrior? Now there's an IDE. It's a joy to use. Runs on Mac and Windows. I think there is a Linux version that uses gcc, but I haven't tried it.
(I admit I haven't tried Eclipse yet, but I would be very surprised if it were better than CodeWarrior.)
Everything Just Works in CodeWarrior. I've even got my wife, a web designer who prefers to hand-code her HTML, to use it to write her web pages.
CodeWarrior supports C, C++, Java and inline assembly. If you prefer makefiles, there are command line tools that provide the same compiler. Old versions of CodeWarrior also supported Pascal, but I don't think they do anymore.
The ISO compliance of CodeWarrior's C++ is far superior to Visual C++'s, and has been quite compliant for a very long time. I've been happily using the Standard Template Library in very complex ways, as well as writing my own fancy templates, for several years.
Alexei Alexandrescu used CodeWarrior to develop the heavily templated source code for Modern C++ Design. Visual C++ can't compile it because of its poor compliance to the standard.
It is also available for many embedded systems. Metrowerks was acquired by Motorola a while back, who makes the ColdFire and PowerPC processors that are important in the embedded world.
-
Re:OOPFunny, I thought functional programming was rather different to OOP.
The joke is, that you can do functional programming in C++, after a fashion, but doesn't use many of the OOP concepts to do it!
For my work, C++ allows a programming style better than OOP: a procedural style based around generic algorithms. See, for example, Andrei Alexandrescu's book for an idea of the possibilities. This style is not available in Java because it requires templates, and last time I saw the proposals to add templates to Java, they were rather crippled anyway and wouldn't give the same functionality.
In this style of programming, virtual functions are only used as a kind of 'single dispatch', when you must to invoke polymorphism at runtime, rather than the more robust and safer compile-time polymorphism. And I find myself wanting multiple dispatch as often as I want single dispatch, for which virtual functions don't suffice anyway.
In other words, if all you see in C++ is a not very pure OOP language, then you have missed all of the exiting parts.
-
Re:Don't count on it
My first programs were in FORTRAN, for the moment I'm doing Java, and I'm hoping for Lisp in another 10 years...
Not a bad goal. Lisp has certainly weathered well over the years. It has fallen somewhat out of favor in the past decade. I attribute that to two things. First, it has suffered by association with AI. Second, Lisp is not a language one grasps quickly. The power is contained in idioms and composition of features one with another. That doesn't invite the newbie.
When you can look at Paul Graham's book On Lisp and Andrei Alexandrescu's Modern C++ Design and understand the similarities, you are ready to code in any language. -
Re: Are templates always necessary?SquareOfS wrote:
But far beyond convenience when typing, the important point is that using templates or generics in collections turns the typesafety of collections into a compile-time check rather than a runtime exception.
Templates in C++ go much beyond typesafe collections. As an earlier poster commented, in technical circles it's referred to as "parametric polymorphism". For the layperson, you can think of it as a form of specialized code generation.
The best example of how much bigger they are than typesafe collections is the use of templates for traits and policies. Take the classic reference counted smart pointer, which usually looks like this:
SmartPtr<int> i_sp = new int(5);
cout << *i_sp << endl;
What about the question of whether SmartPtrs should be allowed to hold null pointers? Maybe in some case it's appropriate, but in others an exception should be thrown if it's attempted. Rather than having two different SmartPtr implementation, you add a new template parameters, the OwnershipPolicy type. The SmartPtr author than provides types like AssertCheckStrict and NoCheck. So then your code looks like this:
SmartPtr<int, NoCheck> i_sp = new int(5);
SmartPtr<int, AssertCheckStrict> j_sp new int(6);
This example comes from Alexandrescu's Modern C++ Design, and his Loki framework. -
An excellent book, but be aware
First, there are some significant errata (and a lot of minor typos). Get the errata list and the code for all of the examples from one of the authors at his website. Second, some of these techniques depend on features that aren't yet available in many compilers. Don't expect them all to work yet. They do discuss that in the book.
With that said, I'm not sure that I would have rated this book a 10, but it's close enough that I'm not arguing. It is not a light read, nor should it be. This book and Andrei Alexandrescu's Modern C++ Design have convinced me that C++ templates are much more powerful, useful and complex than I realized. In fact, if I hadn't read Alexandrescu's book first, I wouldn't have thought C++ Templates was missing anything. These two books should be on the shelf of anyone who wants to use the full power of templates. -
Re:C++ Persistence
You need to handle pointers and references, google for pointer swizzling. Garbage Collection by Richard Jones and Rafael D. Lins explains some of the issues involved. Alexei Andresceu's Modern C++ Design gives a sample implementation. This is one of the tasks that reflection, aspect-oriented programming or a meta object protocol makes easier, otherwise you need to add a
.serialize() method to each object. -
Unless, of course, you actually had a clue
Perhaps reading Modern C++ Design would show you that templates are much much more than just generic types.
On the other hand, expecting a Java programmer to trade simplicity for power is just futile. Likewise, asking them to learn something hard to produce something great is likewise a waste of time, they are much more set out on the learn something easy and produce something mediocre mindset.
A conforming C++ compiler is Turing complete, which means you can basically compute anything computable at COMPILE TIME, not just in the binary it produces. -
Re:Downsides
With the STL, C++ has finally aquired a part of what Smalltalk and Java have always had: a library of base classes.
The STL is a library of generics, not base classes. Unless you're talking about unary_function or something. Generally, one should not inherit from STL classes. Inheriting from traits classes is ok (encouraged?).
Why didn't we see these problems before the STL? Because we never tried to use C++ as much more than a superset of C.
This sounds like a second-system effect. Once your team got familiar with C++ and inheritance, the tendancy was to use it everywhere. Happens to everyone.
:)With the STL, we had the opportunity to build things that were more like our other OO systems, so we did. And that's where we started to get bogged down.
My experience was exactly the opposite. Before I learned about the STL and templates, I was trying to shoehorn designs into inheritance heirarchies. Now templates are becoming the preferred method of expression -- the curiously recurring template pattern, for example, can eliminate virtual function calls. Andrei Alexandrescu presents a nice synthesis of generic and object-oriented programming in Modern C++ Design .
-
Re:Not many drawbacks
Kitchen sink syndrome: There are a lot of features in STL, and to use some of them you need functors, etc. Sometimes it's just easier to read if you use a normal for loop instead of using for_each, etc.
This is a known problem in the STL. As some gurus have put it, "STL is not STL enough." What that means is that the STL falls short of using the full power of templates. Check out the Boost bind library (and later, the Lambda Library) for a solution to the for_each problem.
verbose type syntax: When you use the containers, like (say) std::vector, you have to declare your iterators as:
std::vector::iterator i;
If you change to a std::list container, you'll have to change your declarations. Of course, you can mitigate that by using typedefs, and then you only have to change the typedef, but it can still get a bit wordy.
typedef makes this a non-issue. I find the "wordiness" a nice form of in-code documentation.
unexpected results: Understand the difference between remove() and erase() in the containers.
It's unfair to label this "unexpected," but you're right in that knowledge of the API is important. As it is for all libraries.
The benefits of using STL are wonderful. If you write your custom containers/streams/etc. using the STL interface, you can seamlessly use the algorithms portion of the library.
This is the real power of the STL. IMHO too many people concentrate on "containers of X." This goes doubly for the C++ template engine as a whole.
I recommend reading the first part of Generic Programming and the STL. It'll help you undestand the thinking behind the design.
Then get Modern C++ Design , join the Boost mailing list and take it to the next level.
The STL is great. Some of the stuff coming in the next library standard revision is even better. The stuff in Boost is outstanding.
The biggest problem I have had with the STL is convincing people to use it. The available implementations could be better (smaller, more template specialization, etc.) but the savings in programmer time is well worth the slight cost.