Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
As you may have heard, the last meeting of the C++ standards committee voted to remove concepts from the next C++ standard. Of course, this will affect other features and would seem to throw the standard wide open again. If that is the case, which other features do you think should be stripped away (or added), and why?
Links:
Removal of Concepts -- Danny Kalev (on the decision to remove concepts)
Simplifying the use of Concepts -- Bjarne Stroustrup (on the problems with concepts as they look now)
The Long Pole Gets Longer -- Martin Tasker (on the impact to the schedule for C++0x if concepts have to be fixed)
The C++0x "Remove Concepts" Decision - Stroustrup on the issue on Dr. Dobbs
Trip Report: Exit Concepts, Final ISO C++ Draft in ~18 Months - Herb Sutter
Concepts Get Voted Off The C++0x Island - Jeremy Siek defending the current Concepts spec
What Happened in Frankfurt? - Doug Gregor on C++Next (on the history and removal of Concepts).
Of course, this will affect other
features and would seem to throw the
standard wide open again.
Hardly. They still want to wrap up the standard soon, which is one of the main reasons for removing concepts. Making it "wide open" to unrelated changes would just throw away everything they gained by ditching concepts.
Anyway.... Of the remaining C++0x additions, I can't think of anything else I'd want to remove. I agree with their decision regarding concepts though. Stroustrup's paper really outlined some serious problems, The current specification for concepts would admittedly simplify template error messages, but it would do so by dramatically reducing the usefulness of generic programming -- a price I'm not willing to pay.
When I first read that paper, it scared me, because I assumed it was too late in the process for making serious changes to the spec. Turns out it wasn't, and the committee was willing to take dramatic action.
But apart from this, I think C++0x is in good shape. The remaining new features all look worthwhile.
Of course, there are plenty of existing features I'd love to remove. Primarily the vector<bool> specialization. There are other popular examples of features that didn't work out (the export keyword, exception specifications), but the vector specialization is the only one of them that can't be ignored. As long as we don't try to export templates, it doesn't matter that the keyword exists (and isn't implemented by compilers), and we can just refrain from using exception specs, but every time we need a vector of bools, we're bitten by the stupid premature optimization that slipped into the current standard.
Unfortunately, it seems like they've given up on removing it. (Last I checked, it wasn't even deprecated).
Of course, plenty of old C cruft could be ditched too, but recently, I've discovered that the one change I'd really love to see is...... ditching the Iostreams library. Toss it out, and build a new STL-style I/O library based on generic programming.
The current OOP-styled Iostreams library is ugly, slow, overcomplicated and inflexible. There's too much voodoo involved in defining new streams, too few standard stream types involved, too little flexibility (the problem that made me realize how limited the library is, was that I needed to extract a float from a string. Easy to do with stringstream, but if you need to do it often, you don't want to have to copy the input string every time (as the stringstream does) -- where's the stream that works on an existing iterator range? Or a raw array, even?)
Throw IOstreams out, develop a modern replacement, and C++ will be vastly improved.
And perhaps do something about the string class as well. It works sort of ok'ish as it is now, but really, what's with the huge number of member functions? Most of them would work better, and be more general, as free functions. Too much of the standard library relies specifically on the string class, when it could in principle work with any container, or even an iterator (std::getline, I'm looking at you)
Personally, I want C++ to finally break away from C. No more pre-processor, no more header files. I basically want D, but without all the stuff that D tacks on, using the STL.
None, I think the rest of the draft was great - a large number of very small pieces that can be correctly implemented independently, allowing vendors to evolve toward complete support and allowing users to take a "shopping list" approach.
Quite a different situation with contracts, as they were like a whole new parallel type system and would have been very likely to have led to different compilers ending up with their own backward compatibility problems, very similar to CSS in web browsers.
There are two things I think should be added to C++0x, I've thought of both these myself and then found that others have suggested them before but it doesn't seem like they're going to happen.
1. Defaulting Move Constructors and Move Assignment Operators
Writing a move constructor is a manual and error prone activity, if a member is added it must be added to the move constructor and assignment operators and std::move must be used religiously. That's why I think these functions should be defaultable.
movable(movable&&) = default;
movable& operator=(movable&&) = default;
Edit (2009-10-01): Looks like this is going to happen after all.
2. Override Type Deduction for Expression Templates
Expression templates often define types that should not be used directly, a case in point is the return value of std::vector<bool> operator[](size_type n), if auto or decltype are used on this kind of object unexpected behaviour may ensue.
Therefore a type should be able to say what type it should be deduced to be (or prevent deduction using = delete syntax).
Example for vector addition.
// lazy evaluation of vector addition
template<typename T, class V1, class V2>
class vector_add {
V1& lhs_;
V2& rhs_;
public:
T operator[](size_t n) const
{ return lhs_[n] + rhs_[n]; }
// If used by auto or decltype perform eager creation of vector
std::vector<T> operator auto() const
{
if (lhs_.size() != rhs_.size())
throw std::exception("Vectors aren't same size");
std::vector<T> vec;
vec.reserve(lhs_.size());
for (int i = 0; i < lhs_.size(); ++i)
vec.push_back(lhs_[i] + rhs_[i]);
return vec;
}
To me the problem is not what other features should be stripped away, but how complex will other features be after concepts have been removed. That and how much longer will it take for the rest of the features to be rephrased without concepts.
A lot of features assumed that concepts would be accepted into the language and the wording is expressed in terms of concepts. (I wonder if any proposed feature depends on concepts).
I also wonder how other libraries will evolve (think boost::type_traits) to take the niche left by concepts. Part of what concepts provided can be implemented (even if in a more cumbersome way) in terms of traits applied to the type arguments.
To me, the most important thing that concepts added to the language was an expressive formulation of compilation errors, which is nowadays one of the places where C++ is most criticized.
R.I.P. concepts.
Do whatever you want with concepts, but for god's sake keep threads and atomics, we absolutely need them. Perhaps add thread groups and support for cooperative threads a.k.a. fibers. IMO these are far more important than concepts, because everyone uses/will soon be using threads.
I'd like to remove =delete.
There's already a common and accepted idiom for acheiving the same effect (declare the function in question as private). I think this feature will just generate lots of 'I used =delete to remove a base class function from my derived class, but it can still be called using a base class pointer' questions.
Not to mention confusing people between the (now) two meanings of the delete keyword.
Strip away the pages of error messages on template code!
IIRC concepts should solve a big C++ coder problem: Human readable error messages for the STL. Its bad news that this issue isn't addressed.
The un-named function / lambda function stuff makes me nervous. Function objects are perfectly good and are explicit, thus easier to read and find.
On the other hand I kinda liked concepts, though I certainly would not have used them every day.
Related
Also on programmers.stackexchange.com:
I understand that STL concepts had to exist, and that it would be silly to call them "classes" or "interfaces" when in fact they're only documented (human) concepts and couldn't be translated into C++ code at the time, but when given the opportunity to extend the language to accomodate concepts, why didn't they simply modify the capabilities of classes and/or introduced interfaces?
Isn't a concept very similar to an interface (100% abstract class with no data)? By looking at it, it seems to me interfaces only lack support for axioms, but maybe axioms could be introduced into C++'s interfaces (considering an hypothetical adoption of interfaces in C++ to take over concepts), couldn't them? I think even auto concepts could easily be added to such a C++ interface (auto interface LessThanComparable, anyone?).
Isn't a concept_map very similar to the Adapter pattern? If all the methods are inline, the adapter essentially doesn't exist beyond compile time; the compiler simply replaces calls to the interface with the inlined versions, calling the target object directly during runtime.
I've heard of something called Static Object-Oriented Programming, which essentially means effectively reusing the concepts of object-orientation in generic programming, thus permitting usage of most of OOP's power without incurring execution overhead. Why wasn't this idea further considered?
I hope this is clear enough. I can rewrite this if you think I was not; just let me know.
There is a big difference between OOP and Generic Programming, Predestination.
In OOP, when you design the class, you had the interfaces you think will be useful. And it's done.
In Generic Programming, on the other hand, as long as the class conforms to a given set of requirements (mainly methods, but also inner constants or types), then it fits the bill and may be used. The Concept proposal is about formalizing this, so that detection may occur directly when checking the method signature, rather than when instantiating the method body. It also makes checking template methods more easily, since some methods can be rejected without any instantiation if the concepts do not match.
The advantage of Concepts is that you do not suffer from Predestination, you can pick a class from Library1, pick a method from Library2, and if it fits, you're gold (if it does not, you may be able to use a concept map). In OO, you are required to write a full-fledged Adapter, every time.
You are right that both seem similar. The difference is mainly about the time of binding (and the fact that Concept still have static dispatch instead of dynamic dispatch like with interfaces). Concepts are more open, thus easier to use.
Classes are a form of named conformance. You indicate that class Foo conforms with interface I by inheriting from I.
Concepts are a form of structural and/or runtime conformance. A class Foo does not need to state up front which concepts it conforms to.
The result is that named conformance reduces the ability to reuse classes in places that were not expected up front, even though they would be usable.
The concepts are in fact not part of C++, they are just concepts! In C++ there is no way to "define a concept". All you have is, templates and classes (STL being all template classes, as the name says: S tandard T emplate L ibrary).
If you mean C++0x and not C++ (in which case I suggest you change the tag), please read here:
http://en.wikipedia.org/wiki/Concepts_(C++)
Some parts I am going to copy-paste for you:
In the pending C++0x revision of the C++ programming language, concepts and the related notion of axioms were a proposed extension to C++'s template system, designed to improve compiler diagnostics and to allow programmers to codify in the program some formal properties of templates that they write. Incorporating these limited formal specifications into the program (in addition to improving code clarity) can guide some compiler optimizations, and can potentially help improve program reliability through the use of formal verification tools to check that the implementation and specification actually match.
In July 2009, the C++0x committee decided to remove concepts from the draft standard, as they are considered "not ready" for C++0x.
The primary motivation of the introduction of concepts is to improve the quality of compiler error messages.
So as you can see, concepts are not there to replace interfaces etc, they are just there to help the compiler optimize better and produce better errors.
While I agree with all the posted answers, they seem to have missed one point which is performance. Unlike interfaces, concepts are checked in compile-time and therefore don't require virtual function calls.
I was looking at a job posting recently and one of the requirements was that a person be a 9/10 in their knowledge of STL.
When I judge my skills, to me a 10 is someone that writes advanced books on the subject, such as Jon Skeet (C#), John Resig (JavaScript) or Martin Odersky (Scala).
So, a 9/10 is basically a 10, so I am not certain what would be expected at that level.
An example of some questions would be found at: http://discuss.joelonsoftware.com/default.asp?joel.3.414500.47
Obviously some coding will be needed, but should everything be expected to be memorized, as there is quite a bit in STL.
In some cases Boost libraries extend STL, so should it be expected that I would be using Boost also, as I may sometimes confuse which function came from which of the two libraries.
I am trying to get an idea if I can answer questions that would be expected of a STL expert, though it is odd that being a C++ expert wasn't a requirement.
UPDATE
After reflecting on the answers to my question it appears that what they may be looking for is someone that can see the limits of STL and extend the library, which is something I haven't done. I am used to thinking within the limits of what STL and Boost give me and staying within the lines. I may need to start looking at whether that has been too limiting and see if I can go outside the box. I hope they don't mean a 9 as Google does. :)
Funny -- I don't consider myself a 9/10 in STL (I used to be, but I'm a bit rusty now), and I do fully agree with #joshperry's important terminological distinguo (I've often been on record as berating the abuse of STL to mean "the parts of the C++ standard library that were originally inspired by SGI's STL"!-), yet I consider his example code less than "optimally STL-ish". I mean, for the given task "Put all the integers in a vector to standard out.", why would anyone ever code, as #joshperry suggests,
for(std::vector<int>::iterator it = intVect.begin(); it != intVect.end(); ++i)
std::cout << *it;
rather than the obvious:
std::copy(intVect.begin(), intVect.end(), std::ostream_iterator<int>(std::cout));
or the like?! To me, that would kind of suggest they don't know about std::ostream_iterator -- especially if they're supposed to be showing off their STL knowledge, why wouldn't they flaunt it?-)
At my current employer, to help candidates self-rate about competence in a technology, we provide a helpful guide -- "10: I invented that technology; 9: I wrote THE book about it" and so on down. So, for example, I'd be a 9/10 in Python -- only my colleague and friend Guido can fairly claim a 10/10 there. STL is an interesting case: while Stepanov drove the design, my colleague Matt Austern did the first implementation and wrote "the" book about it, too (this one) -- so I think he'd get to claim, if not a 10, a 9.5. By that standard, I could be somewhere between 7 and 8 if I could take an hour to refresh (custom allocators and traits are always tricky, or at least that's how I recall them!-).
So, if you're probing somebody who claims a 9, grill them over the really hard parts such as custom allocators and traits -- presumably they wouldn't miss a beat on all the containers, algorithms, and special iterators, so don't waste much interview time on those (which would be key if you were probing for a 7 or 7.5). Maybe ask them to give a real-life example where they used custom traits and/or allocators, and code all the details of the implementation as well as a few sample uses.
BTW, if you're the one needing to cram on C++'s standard library at an advanced level, I'm told by knowledgeable and non-rusty friends that Josuttis' book nowadays is even more useful than my friend Matt's (unfortunately, I've never read Josuttis in depth, so I can't confirm or deny that - I do see the book has five stars on Amazon, which is impressive;-).
It is just a dumb requirement for a job. When hiring you want a good great programmer first, specific knowledge second.
It would be reasonable, at this day and age, to expect knowledge/familiarity/etc with the STL. But unless the job is to reimplement the STL, you don't need 9/10. Even if that is the job, you still just need a great programmer that has lots of experience with templates (making not just using).
For example, for all the answers to "output the integers of a vector", probably the exact same code is generated. Only the version that has been templated to handle any container of any items shows a hint of 'great' vs good (just a hint). ie the ability to abstract.
Anyhow, just go for it. Be ready to use the STL to help solve other problems. Nothing more.
(In fact, for most of the interviews I've been in, the requirement was to NOT use the STL. ie - write a function that reverses a string. My first answer is that there is probably something in the std lib that would do that. Then they say, right, of course, but what if you had to write it yourself...)
I should preface this by noting that I think the same criteria should be applied not only to STL (regardless of which definition you prefer for that), but to many other types of things as well.
From my perspective, simply knowing the existing STL components and being able to apply them well probably should not qualify as a 9/10. Rather, I'd consider that level about 7/10. 8/10 is when the person is able to extend the STL by providing new components that follow its philosophy and fit with existing components naturally and easily.
By 9/10, I'd expect to see somebody who can not only provide new components, but is able to improve some of the existing ones, such as Boost::bind. For 10/10, I'd expect to see this go beyond the rather ad hoc, localized improvements of a 9/10, and moving toward looking at a more architectural level, such as using ranges instead of individual iterators. For a concrete example, consider the difference between Boost's ranges and Andrei Alexandrescu's ideas for ranges. Boost's ranges are handy, useful and convenient, but they change what you type, not how you think. Andre's version of ranges is much more all-encompassing -- an architectural solution that changes how you design and think about code, not just how you type it.
Well, you could walk into the interview and say "I noticed that your posting asked for someone knowledgeable in STL but that term is sometimes used to mean: (1) C++ standard library; (2) the library Stepanov designed at HP; (3) the parts of [1] based on [2]; (4) specific vendor implementations of either [1], [2], or [3]; (5) the underlying principles of [2]. As such, the term is highly ambiguous, and must be used with extreme caution. If you meant [1] and insist on abbreviating, "stdlib" is a far better choice."*
Honestly though since it is a library it is somewhat finite and probably not composeable to nauseating infinitum like a language proper. So I would say any question that had them use some of the stdlib algorithms would be effective to see if they knew them well.
With iterators being an integral part of the stdlib I would also maybe ask them to "Put all the integers in a vector to standard out." I would expect something like:
// thanks to onebyone
std::copy(vec.begin(), vec.end(), std::ostream_iterator<int>(std::cout, " ");
If they write something like the following they probably aren't very familiar with iterators:
for(int i = 0; i < vec.size(); ++i)
std::cout << vec[i];
Also one interesting thing to look for is if they do using namespace std at the top of their code file. Ask them why, and if they don't say something along the lines of "I use that for short demo code only" or if they put it in a header file, thank them for coming in and send them out the door.
Another aspect of the stdlib is it's heavy use of templates, the person should have a good understanding of basic template programing for type substitution. Maybe ask them to "Write a function that will write all of items of any stdlib container to standard out". I would expect to see something like:
template<typename InputIter>
void Output(InputIter it, InputIter end) {
while(it != end)
std::cout << *it++;
}
These are probably not 9/10 questions but interesting ones I think a 2-3/10 should know.
One 9/10 difficulty I would say is to write a derived iostream properly without using the boost stream base classes. But there is probably quite a difference between using the stdlib and extending it...
*(thanks to nolyc on freenode ##C++ for the quote)
9/10 is quite subjective. I have been asked good questions about STL. These are examples:
When should you use a deque vs a vector (knowledge of how they are internally implemented is helpful)
Recognize STL code that uses invalid references, or can end up using invalid references.
Implement simple operations on different containers, and know where and when to use std::algorithm vs member functions of a container.
I mean, aside from its name the Standard Template Library (which evolved into the C++ standard library).
C++ initially introduce OOP concepts into C. That is: you could tell what a specific entity could and couldn't do (regardless of how it does it) based on its class and class hierarchy. Some compositions of abilities are more difficult to describe in this manner due to the complexities of multiple inheritance, and the fact that C++ supports interface-only inheritance in a somewhat clumsy way (compared to java, etc), but it's there (and could be improved).
And then templates came into play, along with the STL. The STL seems to take the classical OOP concepts and flush them down the drain, using templates instead.
There should be a distinction between cases when templates are used to generalize types where the types themselves are irrelevant for the operation of the template (containers, for examples). Having a vector<int> makes perfect sense.
However, in many other cases (iterators and algorithms), templated types are supposed to follow a "concept" (Input Iterator, Forward Iterator, etc...) where the actual details of the concept are defined entirely by the implementation of the template function/class, and not by the class of the type used with the template, which is a somewhat anti-usage of OOP.
For example, you can tell the function:
void MyFunc(ForwardIterator<...> *I);
Update: As it was unclear in the original question, ForwardIterator is ok to be templated itself to allow any ForwardIterator type. The contrary is having ForwardIterator as a concept.
expects a Forward Iterator only by looking at its definition, where you'd need either to look at the implementation or the documentation for:
template <typename Type> void MyFunc(Type *I);
Two claims I can make in favor of using templates: 1. Compiled code can be made more efficient, by recompiling the template for each used type, instead of using dynamic dispatch (mostly via vtables). 2. And the fact that templates can be used with native types.
However, I am looking for a more profound reason for abandoning classic OOP in favor of templating for the STL?
The short answer is "because C++ has moved on". Yes, back in the late 70's, Stroustrup intended to create an upgraded C with OOP capabilities, but that is a long time ago. By the time the language was standardized in 1998, it was no longer an OOP language. It was a multi-paradigm language. It certainly had some support for OOP code, but it also had a turing-complete template language overlaid, it allowed compile-time metaprogramming, and people had discovered generic programming. Suddenly, OOP just didn't seem all that important. Not when we can write simpler, more concise and more efficient code by using techniques available through templates and generic programming.
OOP is not the holy grail. It's a cute idea, and it was quite an improvement over procedural languages back in the 70's when it was invented. But it's honestly not all it's cracked up to be. In many cases it is clumsy and verbose and it doesn't really promote reusable code or modularity.
That is why the C++ community is today far more interested in generic programming, and why everyone is finally starting to realize that functional programming is quite clever as well. OOP on its own just isn't a pretty sight.
Try drawing a dependency graph of a hypothetical "OOP-ified" STL. How many classes would have to know about each other? There would be a lot of dependencies. Would you be able to include just the vector header, without also getting iterator or even iostream pulled in? The STL makes this easy. A vector knows about the iterator type it defines, and that's all. The STL algorithms know nothing. They don't even need to include an iterator header, even though they all accept iterators as parameters. Which is more modular then?
The STL may not follow the rules of OOP as Java defines it, but doesn't it achieve the goals of OOP? Doesn't it achieve reusability, low coupling, modularity and encapsulation?
And doesn't it achieve these goals better than an OOP-ified version would?
As for why the STL was adopted into the language, several things happened that led to the STL.
First, templates were added to C++. They were added for much the same reason that generics were added to .NET. It seemed a good idea to be able to write stuff like "containers of a type T" without throwing away type safety. Of course, the implementation they settled on was quite a lot more complex and powerful.
Then people discovered that the template mechanism they had added was even more powerful than expected. And someone started experimenting with using templates to write a more generic library. One inspired by functional programming, and one which used all the new capabilities of C++.
He presented it to the C++ language committee, who took quite a while to grow used to it because it looked so strange and different, but ultimately realized that it worked better than the traditional OOP equivalents they'd have to include otherwise. So they made a few adjustments to it, and adopted it into the standard library.
It wasn't an ideological choice, it wasn't a political choice of "do we want to be OOP or not", but a very pragmatic one. They evaluated the library, and saw that it worked very well.
In any case, both of the reasons you mention for favoring the STL are absolutely essential.
The C++ standard library has to be efficient. If it is less efficient than, say, the equivalent hand-rolled C code, then people would not use it. That would lower productivity, increase the likelihood of bugs, and overall just be a bad idea.
And the STL has to work with primitive types, because primitive types are all you have in C, and they're a major part of both languages. If the STL did not work with native arrays, it would be useless.
Your question has a strong assumption that OOP is "best". I'm curious to hear why. You ask why they "abandoned classical OOP". I'm wondering why they should have stuck with it. Which advantages would it have had?
The most direct answer to what I think you're asking/complaining about is this: The assumption that C++ is an OOP language is a false assumption.
C++ is a multi-paradigm language. It can be programmed using OOP principles, it can be programmed procedurally, it can be programmed generically (templates), and with C++11 (formerly known as C++0x) some things can even be programmed functionally.
The designers of C++ see this as an advantage, so they would argue that constraining C++ to act like a purely OOP language when generic programming solves the problem better and, well, more generically, would be a step backwards.
My understanding is that Stroustrup originally preferred an "OOP-styled" container design, and in fact didn't see any other way to do it. Alexander Stepanov is the one responsible for the STL, and his goals did not include "make it object oriented":
That is the fundamental point: algorithms are defined on algebraic structures. It took me another couple of years to realize that you have to extend the notion of structure by adding complexity requirements to regular axioms. ... I believe that iterator theories are as central to Computer Science as theories of rings or Banach spaces are central to Mathematics. Every time I would look at an algorithm I would try to find a structure on which it is defined. So what I wanted to do was to describe algorithms generically. That's what I like to do. I can spend a month working on a well known algorithm trying to find its generic representation. ...
STL, at least for me, represents the only way programming is possible. It is, indeed, quite different from C++ programming as it was presented and still is presented in most textbooks. But, you see, I was not trying to program in C++, I was trying to find the right way to deal with software. ...
I had many false starts. For example, I spent years trying to find some use for inheritance and virtuals, before I understood why that mechanism was fundamentally flawed and should not be used. I am very happy that nobody could see all the intermediate steps - most of them were very silly.
(He does explain why inheritance and virtuals -- a.k.a. object oriented design "was fundamentally flawed and should not be used" in the rest of the interview).
Once Stepanov presented his library to Stroustrup, Stroustrup and others went through herculean efforts to get it into the ISO C++ standard (same interview):
The support of Bjarne Stroustrup was crucial. Bjarne really wanted STL in the standard and if Bjarne wants something, he gets it. ... He even forced me to make changes in STL that I would never make for anybody else ... he is the most single minded person I know. He gets things done. It took him a while to understand what STL was all about, but when he did, he was prepared to push it through. He also contributed to STL by standing up for the view that more than one way of programming was valid - against no end of flak and hype for more than a decade, and pursuing a combination of flexibility, efficiency, overloading, and type-safety in templates that made STL possible. I would like to state quite clearly that Bjarne is the preeminent language designer of my generation.
The answer is found in this interview with Stepanov, the author of the STL:
Yes. STL is not object oriented. I
think that object orientedness is
almost as much of a hoax as Artificial
Intelligence. I have yet to see an
interesting piece of code that comes
from these OO people.
Why a pure OOP design to a Data Structure & Algorithms Library would be better ?!
OOP is not the solution for every thing.
IMHO, STL is the most elegant library I have seen ever :)
for your question,
you don't need runtime polymorphism, it is an advantage for STL actually to implement the Library using static polymorphism, that means efficiency.
Try to write a generic Sort or Distance or what ever algorithm that applies to ALL containers!
your Sort in Java would call functions that are dynamic through n-levels to be executed!
You need stupid thing like Boxing and Unboxing to hide nasty assumptions of the so called Pure OOP languages.
The only problem I see with STL, and templates in general is the awful error messages.
Which will be solved using Concepts in C++0X.
Comparing STL to Collections in Java is Like comparing Taj Mahal to my house :)
templated types are supposed to follow
a "concept" (Input Iterator, Forward
Iterator, etc...) where the actual
details of the concept are defined
entirely by the implementation of the
template function/class, and not by
the class of the type used with the
template, which is a somewhat
anti-usage of OOP.
I think you misunderstand the intended use of concepts by templates. Forward Iterator, for example, is a very well-defined concept. To find the expressions which must be valid in order for a class to be a Forward Iterator, and their semantics including computational complexity, you look at the standard or at http://www.sgi.com/tech/stl/ForwardIterator.html (you have to follow the links to Input, Output, and Trivial Iterator to see it all).
That document is a perfectly good interface, and "the actual details of the concept" are defined right there. They are not defined by the implementations of Forward Iterators, and neither are they defined by the algorithms which use Forward Iterators.
The differences in how interfaces are handled between STL and Java are three-fold:
1) STL defines valid expressions using the object, whereas Java defines methods which must be callable on the object. Of course a valid expression might be a method (member function) call, but it doesn't have to be.
2) Java interfaces are runtime objects, whereas STL concepts are not visible at runtime even with RTTI.
3) If you fail to make valid the required valid expressions for an STL concept, you get an unspecified compilation error when you instantiate some template with the type. If you fail to implement a required method of a Java interface, you get a specific compilation error saying so.
This third part is if you like a kind of (compile-time) "duck typing": interfaces can be implicit. In Java, interfaces are somewhat explicit: a class "is" Iterable if and only if it says it implements Iterable. The compiler can check that the signatures of its methods are all present and correct, but the semantics are still implicit (i.e. they're either documented or not, but only more code (unit tests) can tell you whether the implementation is correct).
In C++, like in Python, both semantics and syntax are implicit, although in C++ (and in Python if you get the strong-typing preprocessor) you do get some help from the compiler. If a programmer requires Java-like explicit declaration of interfaces by the implementing class, then the standard approach is to use type traits (and multiple inheritance can prevent this being too verbose). What's lacking, compared with Java, is a single template which I can instantiate with my type, and which will compile if and only if all the required expressions are valid for my type. This would tell me whether I've implemented all the required bits, "before I use it". That's a convenience, but it's not the core of OOP (and it still doesn't test semantics, and code to test semantics would naturally also test the validity of the expressions in question).
STL may or may not be sufficiently OO for your taste, but it certainly separates interface cleanly from implementation. It does lack Java's ability to do reflection over interfaces, and it reports breaches of interface requirements differently.
you can tell the function ... expects a Forward Iterator only by
looking at its definition, where you'd need either to look at the
implementation or the documentation for ...
Personally I think that implicit types are a strength, when used appropriately. The algorithm says what it does with its template parameters, and the implementer makes sure those things work: it's exactly the common denominator of what "interfaces" should do. Furthermore with STL, you're unlikely to be using, say, std::copy based on finding its forward declaration in a header file. Programmers should be working out what a function takes based on its documentation, not just on the function signature. This is true in C++, Python, or Java. There are limitations on what can be achieved with typing in any language, and trying to use typing to do something it doesn't do (check semantics) would be an error.
That said, STL algorithms usually name their template parameters in a way which makes it clear what concept is required. However this is to provide useful extra information in the first line of the documentation, not to make forward declarations more informative. There are more things you need to know than can be encapsulated in the types of the parameters, so you have to read the docs. (For example in algorithms which take an input range and an output iterator, chances are the output iterator needs enough "space" for a certain number of outputs based on the size of the input range and maybe the values therein. Try strongly typing that.)
Here's Bjarne on explicitly-declared interfaces: http://www.artima.com/cppsource/cpp0xP.html
In generics, an argument must be of a
class derived from an interface (the
C++ equivalent to interface is
abstract class) specified in the
definition of the generic. That means
that all generic argument types must
fit into a hierarchy. That imposes
unnecessary constraints on designs
requires unreasonable foresight on the
part of developers. For example, if
you write a generic and I define a
class, people can't use my class as an
argument to your generic unless I knew
about the interface you specified and
had derived my class from it. That's
rigid.
Looking at it the other way around, with duck typing you can implement an interface without knowing that the interface exists. Or someone can write an interface deliberately such that your class implements it, having consulted your docs to see that they don't ask for anything you don't already do. That's flexible.
"OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things. It can be done in Smalltalk and in LISP. There are possibly other systems in which this is possible, but I'm not aware of them." - Alan Kay, creator of Smalltalk.
C++, Java, and most other languages are all pretty far from classical OOP. That said, arguing for ideologies is not terribly productive. C++ is not pure in any sense, so it implements functionality that seems to make pragmatic sense at the time.
STL started off with the intention of provide a large library covering most commonly used algorithm -- with the target of consitent behavior and performance. Template came as a key factor to make that implementation and target feasible.
Just to provide another reference:
Al Stevens Interviews Alex Stepanov, in March 1995 of DDJ:
http://www.sgi.com/tech/stl/drdobbs-interview.html
Stepanov explained his work experience and choice made towards a large library of algorithm, which eventually evolved into STL.
Tell us something about your long-term interest in generic programming
.....Then I was offered a job at Bell Laboratories working in the C++ group on C++ libraries. They asked me whether I could do it in C++. Of course, I didn't know C++ and, of course, I said I could. But I couldn't do it in C++, because in 1987 C++ didn't have templates, which are essential for enabling this style of programming. Inheritance was the only mechanism to obtain genericity and it was not sufficient.
Even now C++ inheritance is not of much use for generic programming. Let's discuss why. Many people have attempted to use inheritance to implement data structures and container classes. As we know now, there were few if any successful attempts. C++ inheritance, and the programming style associated with it are dramatically limited. It is impossible to implement a design which includes as trivial a thing as equality using it. If you start with a base class X at the root of your hierarchy and define a virtual equality operator on this class which takes an argument of the type X, then derive class Y from class X. What is the interface of the equality? It has equality which compares Y with X. Using animals as an example (OO people love animals), define mammal and derive giraffe from mammal. Then define a member function mate, where animal mates with animal and returns an animal. Then you derive giraffe from animal and, of course, it has a function mate where giraffe mates with animal and returns an animal. It's definitely not what you want. While mating may not be very important for C++ programmers, equality is. I do not know a single algorithm where equality of some kind is not used.
The basic problem with
void MyFunc(ForwardIterator *I);
is how do you safely get the type of the thing the iterator returns? With templates, this is done for you at compile time.
For a moment, let's think of the standard library as basically a database of collections and algorithms.
If you've studied the history of databases, you undoubtedly know that back in the beginning, databases were mostly "hierarchical". Hierarchical databases corresponded very closely to classical OOP--specifically, the single-inheritance variety, such as used by Smalltalk.
Over time, it became apparent that hierarchical databases could be used to model almost anything, but in some cases the single-inheritance model was fairly limiting. If you had a wooden door, it was handy to be able to look at it either as a door, or as a piece of some raw material (steel, wood, etc.)
So, they invented network model databases. Network model databases correspond very closely to multiple inheritance. C++ supports multiple inheritance completely, while Java supports a limited form (you can inherit from only one class, but can also implement as many interfaces as you like).
Both hierarchical model and network model databases have mostly faded from general purpose use (though a few remain in fairly specific niches). For most purposes, they've been replaced by relational databases.
Much of the reason relational databases took over was versatility. The relational model is functionally a superset of the network model (which is, in turn, a superset of the hierarchical model).
C++ has largely followed the same path. The correspondence between single inheritance and the hierarchical model and between multiple inheritance and the network model are fairly obvious. The correspondence between C++ templates and the hierarchical model may be less obvious, but it's a pretty close fit anyway.
I haven't seen a formal proof of it, but I believe the capabilities of templates are a superset of those provided by multiple inheritance (which is clearly a superset of single inerhitance). The one tricky part is that templates are mostly statically bound--that is, all the binding happens at compile time, not run time. As such, a formal proof that inheritance provides a superset of the capabilities of inheritance may well be somewhat difficult and complex (or may even be impossible).
In any case, I think that's most of the real reason C++ doesn't use inheritance for its containers--there's no real reason to do so, because inheritance provides only a subset of the capabilities provided by templates. Since templates are basically a necessity in some cases, they might as well be used nearly everywhere.
This question has many great answers. It should also be mentioned that templates supports an open design. With the current state of object oriented programming languages, one has to use the visitor pattern when dealing with such problems, and true OOP should support multiple dynamic binding. See Open Multi-Methods for C++, P. Pirkelbauer, et.al. for very intersting reading.
Another interesting point of templates are that they can be used on for runtime polymorphism as well. For example
template<class Value,class T>
Value euler_fwd(size_t N,double t_0,double t_end,Value y_0,const T& func)
{
auto dt=(t_end-t_0)/N;
for(size_t k=0;k<N;++k)
{y_0+=func(t_0 + k*dt,y_0)*dt;}
return y_0;
}
Notice that this function will also work if Value is a vector of some kind (not std::vector, which should be called std::dynamic_array to avoid confusion)
If func is small, this function will gain a lot from inlining. Example usage
auto result=euler_fwd(10000,0.0,1.0,1.0,[](double x,double y)
{return y;});
In this case, you should know the exact answer (2.718...), but it is easy to construct a simple ODE without elementary solution (Hint: use a polynomial in y).
Now, you have a large expression in func, and you use the ODE solver in many places, so your executable gets polluted with template instantiations everywhere. What to do? First thing to notice is that a regular function pointer works. Then you want to add currying so you write an interface and an explicit instantiation
class OdeFunction
{
public:
virtual double operator()(double t,double y) const=0;
};
template
double euler_fwd(size_t N,double t_0,double t_end,double y_0,const OdeFunction& func);
But the above instantiation only works for double, why not write the interface as template:
template<class Value=double>
class OdeFunction
{
public:
virtual Value operator()(double t,const Value& y) const=0;
};
and specialize for some common value types:
template double euler_fwd(size_t N,double t_0,double t_end,double y_0,const OdeFunction<double>& func);
template vec4_t<double> euler_fwd(size_t N,double t_0,double t_end,vec4_t<double> y_0,const OdeFunction< vec4_t<double> >& func); // (Native AVX vector with four components)
template vec8_t<float> euler_fwd(size_t N,double t_0,double t_end,vec8_t<float> y_0,const OdeFunction< vec8_t<float> >& func); // (Native AVX vector with 8 components)
template Vector<double> euler_fwd(size_t N,double t_0,double t_end,Vector<double> y_0,const OdeFunction< Vector<double> >& func); // (A N-dimensional real vector, *not* `std::vector`, see above)
If the function had been designed around an interface first, then you would have been forced to inherit from that ABC. Now you have this option, as well as function pointer, lambda, or any other function object. The key here is that we must have operator()(), and we must be able to do use some arithmetic operators on its return type. Thus, the template machinery would break in this case if C++ did not have operator overloading.
How do you do comparisons with ForwardIterator*'s? That is, how do you check if the item you have is what you're looking for, or you've passed it by?
Most of the time, I would use something like this:
void MyFunc(ForwardIterator<MyType>& i)
which means I know that i is pointing to MyType's, and I know how to compare those. Though it looks like a template, it isn't really (no "template" keyword).
The concept of separating interface from interface and being able to swap out the implementations is not intrinsic to Object-Oriented Programming. I believe it's an idea that was hatched in Component-Based Development like Microsoft COM. (See my answer on What is Component-Driven Development?) Growing up and learning C++, people were hyped out inheritance and polymorphism. It wasn't until 90s people started to say "Program to an 'interface', not an 'implementation'" and "Favor 'object composition' over 'class inheritance'." (both of which quoted from GoF by the way).
Then Java came along with built-in garbage collector and interface keyword, and all of a sudden it became practical to actually separate interface and implementation. Before you know it the idea became part of the OO. C++, templates, and STL predates all of this.
Recently I started reading (just a bit) the current draft for the future C++11 standard.
There are lots of new features, some of them already available via Boost Libs. Of course, I'm pretty happy with this new standard and I'd like to play with all the new features as soon as possibile.
Anyway, speaking about this draft with some friends, long-time C++ devs, some worries emerged. So, I ask you (to answer them):
1) The language itself
This update is huge, maybe too huge for a single standard update. Huge for the compiler vendors (even if most of them already started implementing some features) but also for the end-users.
In particular, a friend of mine told me "this is a sort of new language".
Can we consider it a brand new language after this update?
Do you plan to switch to the new standard or keep up with the "old" standard(s)?
2) Knowledge of the language
How the learning curve will be impacted by the new standard?
Teaching the language will be more difficult?
Some features, while pretty awesome, seem a bit too "academic" to me (as definition I mean). Am I wrong?
Mastering all these new additions could be a nightmare, couldn't it?
In short, no, we can't consider this a new language. It's the same language, new features. But instead of being bolted on by using the Boost libs, they're now going to be standard inclusions if you're using a compiler that supports the 0x standard.
One doesn't have to use the new standard while using a compiler that supports the new standard. One will have to learn and use the new standard if certain constraints exist on the software being developed, however, but that's a constraint with any software endeavor. I think that the new features that the 0x standard brings will make doing certain things easier and less error prone, so it's to one's advantage to learn what the new features are, and how they will improve their design strategy for future work. One will also have to learn it so that when working on software developed with it, they will understand what's going on and not make large boo-boos.
As to whether I will "switch to the new standard", if that means that I will learn the new standard and use it where applicable and where it increases my productivity, then yes, I certainly plan to switch. However, if this means that I will limit myself to only working with the new features of the 0x standard, then no, since much of my work involves code written before the standard and it would be a colossal undertaking to redesign everything to use the new features. Not only that, but it may introduce new bugs and performance issues that I'm not aware of without experience.
Learning C++ has always been one of the more challenging journeys a programmer can undertake. Adding new features to the language will not change the difficulty of learning its syntax and how to use it effectively, but the approach will change. People will still learn about pointers and how they work, but they'll also learn about smart pointers and how they're managed. In some cases, people will learn things differently than before. For example, people will still need to learn how to initialize things, but now they'll learn about Uniform Initialization and Initializer Lists as primary ways to do things. In some cases, perhaps understanding things will be easier with the addition of the new for syntax for ranges or the auto return type in a function declaration. I think that overall, C++ will become easier to learn and use while at the same time becoming easier to teach.
Mastering a language is a long-term goal, it can not be done over night. It's silly to think that one can have mastery over something as complex as C++ quickly. It takes practice, experience and debugging code to really hammer something in. Academically learning is one thing, but putting to use that knowledge is an entire different monster. I think that if one already has mastery of the C++ language, the new concepts will not pose too much of a burden, but a new comer may have an advantage in that they won't bother learning some of the more obsolete ways of doing things.
1) The language itself
As far as I'm aware, there are really no breaking changes between
C++'03 and C++'0x. The only one I can think of here relates to using
auto as a storage class specifier, but since it had no semantic
meaning I don't see that being an issue.
There are a lot of other academic fixes to the standard which are very
necssary, for example better descriptions for the layout of member
data. Finally, with multi-core/cpu architectures becoming the norm,
fixing the memory model was a must.
2) Knowledge of the language
Personally, I feel that for 99.9% of C++ developers the newer language is going to be easier to use. I'm specifically thinking of features such as auto, lambda's and constexpr. These features really should make using the language more enjoyable.
At a more advanced level, you have other features such as variadic
templates etc that help the more advanced users.
But there's nothing new here, I'm still surprised at the amount of
everyday C++ developers that haven't used (or even heard of) the STL.
From a personal perspective, the only feature I'm a bit concerned about in the new standard is that of concepts. As it is such a large change, the same problems that occurred with templates (ie. completely broken implementations) is a real danger.
Update post FDIS going out for voting:
As it happens, 'concepts' was dropped for C++ 0x and will be taken up again for C++ 1x. In the end there are some changes other than auto which could break your code, but in practise they'll probably be pretty rare. The key differences can be found in Appendix C.2 of the FDIS (pdf).
For me, one of the most important, will be:
unique_ptr + std::move() !
Imagine:
Smart pointer without any overhead:
no reference counting operations
no additional storage for reference counter variable
Smart pointer that can be moved, ie. no destructor/constructor calls when moved
What does this give you? Exception safe, cheap (pointers..) containers without any costs. The container will be able to just memcpy() unique_ptrs, so there will be no performance loss caused by wrapping regular pointer by smart pointer! So, once again:
You can use pointers
It will be safe (no memory leaks)
It will cost you nothing
You will be able to store them in containers, and they will be able to do "massive" moves (memcpy-like) with them cheaply.
It will be exception safe
:)
Another point of view:
Actually, when you move group of objects using copy(), there is constructor and destructor call for every object instance. When you copy 1000 objects of 1kb size, there will be at least one memcpy() and 2000 function calls.
If you would want to avoid the thousands of calls, you would have to use pointers.
But pointers are: dangerous, etc. Actual smart pointers will not help you, they solve other problems.
There is no solution for now. You must pay for C++ RAII/pointer/valuevars design from time to time. But with C++0x, using unique_ptr will allow to do "massive" moves of objects (yes, practically objects, because pointer will be smart) without "massive" constructor/destructor calls, and without risk of using pointers! For me, this is really important.
It's like relaxing the RAII concept (because of using pointers) without loosing RAII benefits. Another aspect: pointer wrapped in unique_ptr() will behave in many aspects similar to java reference object variable. The difference is that unique_ptr() will be able to exist in only one scope at a time.
Your friend is partially right but mostly wrong: it's the same language with extra features.
The good thing is, you don't have to master all the new features. One of the primary mandates for a standards body is to not break existing code, so you'll be able to go on, happily coding in your old style (I'm still mostly a C coder even though I do "C++" applications :-).
Only when you want to have a look at the new features will you need to bone up on the changes. This is a process you can stretch over years if need be.
My advice is to learn what all the new features are at a high level (if only to sound knowledgeable in job interviews) but learn the details slowly.
In some respects, C++0x should be easier to teach/learn than current C++:
Looping through a container - the new for syntax is far easier than for_each + functor or looping manually using iterators
Initialising containers: we'll be able to initialise sequences with the same syntax as arrays
Memory management: out goes dodgy old auto_ptr, in comes well-defined unique_ptr and shared_ptr
Lambdas, although necessarily more complex than other languages' equivalents, will be easier to learn than the C++98 process of defining function objects in a different scope.
Do you plan to switch to the new standard or keep up with the "old" standard(s)?
A year ago, I was writing strict C89, because the product in question was aggressively portable to embedded platforms, some of which had compilers with radically different ideas of which bits of C99 it's worth supporting. So a 20-year-old standard still hasn't been fully replaced by its 10-year-old successor.
So I don't expect to be able to get away from C++03 any time soon.
I do expect to use C++0x features where appropriate. Just as I use C99 features in C code, and gcc extensions in C and C++ (and would use MSVC extensions, although I've never worked on MSVC-only code for more than trivial amounts of time). But I expect it to be "nice to have" rather than baseline, pretty much indefinitely.
You have a point, but it's always been the case. There is a lot of C++ code out there that still doesn't incorporate anything from the '98 standard just because of the innate conservatism of some coders. Some of us remember a dark time before the std:: namespace (before namespaces, in fact), when everyone wrote their own string class, and pointers walked around naked all the time. There is a reason why we talk about "modern C++ style" - to distinguish from the earlier style because some people still have to maintain or update code in that style.
Any language has to evolve to survive, and any language that evolves will have a divided user base, if only because people vary in their attitude towards estimating opportunity costs in applying new language features to their own work.
With the advent of C++0x in shipping compilers, this conversation will be played out over and over in dev teams across the world:
YOUNGSTER: I've just discovered these things called lambdas! And I'm finding lots of ways to use them to make our code more expressive! Look, I rewrote your old Foo class, isn't that much neater?
OLDSTER: There was nothing wrong with my old Foo class. You're just looking for excuses to use a "cool" new feature unnecessarily. Why do you keep trying to make my life so complicated? Why do I keep having to learn new things? We need another war, that's what we need.
YOUNGSTER: You're just too stuck in your ways, old man, we shouldn't even be using C++ these days... if it was up to me -
OLDSTER: If it was up to me we'd have stuck with PL/1, but no... my wife had to vote for Carter and now we're stuck with all this object-oriented crap. There's nothing you can do with std::transform and lambdas that I can't do with a goto and a couple of labels.
etc.
Your programming career will always involve learning and re-learning. You can't expect c++ to stay the same till you retire and to be using the same methods and practises that you were using 40 years ago. Technology rolls on, and it rolls quickly. It's your job to keep up with it. Of course you can ignore that, and continue to work the same way you currently do, but in 5 / 10 years time you'll become so outdated that you'll be forced to learn it all then when you're trying to change job. And it will have been a lot easier to learn on the job all those years before :)
A few months ago I heard Bjarne Stroustrup give a talk titled 50 years of C++. Admittedly, I'm not a C++ programmer, but it seemed to me that he certainly doesn't think 0x is a new language!
Whether or not we can consider it a "new language", I think that's semantics. It doesn't make a difference. It's backwards compatible with our current C++ code, and it's a better language. Whether or not we consider it "the same language" doesn't matter.
About learning the language, remember that a lot of the new features are there to make the language easier to learn and use. Most of the features that add complexity are intended for library developers only. They can use these new features to make better, more efficient, and easier to use libraries, that you can then use without knowing about the features. Several of the changes actually simplify and generalize existing features, making them easier for newcomers to learn.
It is a big update, yes, but it is guided by a decade of experience with the current C++ standard. Every change is there because experience has shown that it is needed. In fact, the committee is being extremely cautious and conservative, and have refused a huge number of other language improvements. What is added here is only the fundamentals that 1) everyone could agree on, and 2) could be specified in time, without delaying the new standard.
It is not simply a few language designers sitting down and brainstorming new features they'd like to try.
Concepts and Concept Maps are going to greatly increase the grokability of template frameworks. If you've ever poured over the Boost source you'll know what I mean. You're constantly going from source to docs because the language just doesn't have the facilities to express template concepts. Hopefully Concepts + Duck Typing will give us the best of both worlds whereby entry points to template libraries can explicitly declare requirements but still have the freedom that Duck Typing provides when writing generic code.
There are lots of good things in C++0x, but they're mostly evolutionary changes that refine or extend existing ideas. I don't think it's different enough to justify calling it a "new language".
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I've been talking with friends and some completely agree that templates in C++ should be used, others disagree entirely.
Some of the good things are:
They are more safe to use (type safety).
They are a good way of doing generalizations for APIs.
What other good things can you tell me about C++ templates?
What bad things can you tell me about C++ templates?
Edit: One of the reasons I'm asking this is that I am studying for an exam and at the moment I am covering the topic of C++ templates. So I am trying to understand a bit more on them.
Templates are a very powerful mechanism which can simplify many things. However to use them properly requires much time and experience - in order to decide when their usage is appropriate.
For me the most important advantages are:
reducing the repetition of code (generic containers, algorithms)
reducing the repetition of code advanced (MPL and Fusion)
static polymorphism (=performance) and other compile time calculations
policy based design (flexibility, reusability, easier changes, etc)
increasing safety at no cost (i.e. dimension analysis via Boost Units, static assertions, concept checks)
functional programming (Phoenix), lazy evaluation, expression templates (we can create Domain-specific embedded languages in C++, we have great Proto library, we have Blitz++)
other less spectacular tools and tricks used in everyday life:
STL and the algorithms (what's the difference between for and for_each)
bind, lambda (or Phoenix) ( write clearer code, simplify things)
Boost Function (makes writing callbacks easier)
tuples (how to genericly hash a tuple? Use Fusion for example...)
TBB (parallel_for and other STL like algorithms and containers)
Can you imagine C++ without templates? Yes I can, in the early times you couldn't use them because of compiler limitations.
Would you write in C++ without templates? No, as I would lose many of the advantages mentioned above.
Downsides:
Compilation time (for example throw in Sprit, Phoenix, MPL and some Fusion and you can go for a coffee)
People who can use and understand templates are not that common (and these people are useful)
People who think that they can use and understand templates are quite common (and these people are dangerous, as they can make a hell out of your code. However most of them after some education/mentoring will join the group mentioned in the previous point)
template export support (lack of)
error messages could be less cryptic (after some learning you can find what you need, but still...)
I highly recommend the following books:
C++ Templates: The Complete Guide by David Vandevoorde and Nicolai Josuttis (thorough introduction to the subject of templates)
Modern C++ Design. Generic Programming and Design Patterns Applied by Andrei Alexandrescu (what is the less known way of using templates to simplify your code, make development easier and result in code robust to changes)
C++ Template Metaprogramming by David Abrahms and Aleksey Gutov (again - different way of using the templates)
More C++ Idioms from Wikibooks presents some nice ideas.
On the positive side, C++ templates:
Allow for generalization of type
Decrease the amount of redundant code you need to type
Help to build type-safe code
Are evaluated at compile-time
Can increase performance (as an alternative to polymorphism)
Help to build very powerful libraries
On the negative side:
Can get complicated quickly if one isn't careful
Most compilers give cryptic error messages
It can be difficult to use/debug highly templated code
Have at least one syntactic quirk ( the >> operator can interfere with templates)
Help make C++ very difficult to parse
All in all, careful consideration should be used as to when to use templates.
My 2c are rather negative.
C++ types were never designed to perform compile time calculations.
The notion of using types to achieve computational goals is very
clearly a hack – and moreover, one that was never sought but rather
stumbled upon
..
The reward for using MP in your code is the moment of satisfaction of
having solved a hard riddle. You did stuff in 100 lines that would
have otherwise taken 200. You grinded your way through
incomprehensible error messages to get to a point where if you needed
to extend the code to a new case, you would know the exact 3-line
template function to overload. Your maintainers, of course, would have
to invest infinitely more to achieve the same.
Good points: powerful; allows you to:
prescribe compile-time attributes and computation
describe generic algorithms and datastructures
do many other things that would otherwise be repetitive, boring, and mistake-prone
does them in-language, without macros (which can be far more hazardous and obscure!)
Bad points: powerful; allows you to:
provoke compile-time errors that are verbose, misleading, and obscure (though not as obscure and misleading as macros...)
create obscure and hazardous misdesigns (though not as readily as macros...)
cause code bloat if you're not careful (just like macros!)
Templates vastly increase the viable design space, which is not necessarily a bad thing, but it does make them that much harder to use well. Template code needs maintainters who understand not just the language features, but the design consequences of the language features; practically speaking, this means many developer groups avoid all but the simplest and most institutionalized applications of C++ templates.
In general, templates make the language much more complicated (and difficult to implement correctly!). Templates were not intentionally designed to be Turing-complete, but they are anyway -- thus, even though they can do just about anything, using them may turn out to be more trouble than it's worth.
Templates should be used sparingly.
"Awful to debug" and "hard to read" aren't great arguments against good template uses with good abstractions.
Better negative arguments would go towards the fact that the STL has a lot of "gotchas", and using templates for purposes the STL already covers is reinventing the wheel. Templates also increase link time, which can be a concern for some projects, and have a lot of idiosyncrasies in their syntax that can be arcane to people.
But the positives with generic code reuse, type traits, reflection, smart pointers, and even metaprograms often outweigh the negatives. The thing you have to be sure of is that templates are always used carefully and sparingly. They're not the best solution in every case, and often not even the second or third best solution.
You need people with enough experience writing them that they can avoid all the pitfalls and have a good radar for when the templates will complicate things more than helping.
One of the disadvantages I haven't seen mentioned yet is the subtle semantic differences between regular classes and instantiations of class templates. I can think of:
typedefed typenames in ancestor types aren't inherited by template classes.
The need to sprinkle typename and template keywords in appropriate places.
Member function templates cannot be virtual.
These things can usually be overcome, but they're a pain.
Some people hate templates (I do) because:
On maintainability pov, the wrong use of templates can have a negative effect ten times stronger than the initial advantage of time they were supposed to bring.
On optimization pov, compiler optimizations they allow are nothing compared to an optimal algorithm and the use of multi threading.
On compiling time pov, wrong use of templates can a very negative effect on parsing, compilation and linking phases, when poorly written templated declaration brings tons of useless parasite declarations in each compilation units (here is how 200 lines of code can produce an .obj of 1Mb).
To me templates are like a chainsaw with an integrated flame thrower that can also launch grenades. One time in my life I may have a specific need of that. But most of the time, I'm using a regular hammer and a simple saw to build things and I'm doing a pretty good job that way.
Advantage: Generic Datatypes can be created.
Disadvantage: Code Bloating
I don't see how they are hard to read. What is unreadable about
vector <string> names;
for example? What would you replace it with?
Reusable code is made with template. Its application is in accordance with the profile of each.