A week ago, I attended the summer ISO C++ meeting in Frankfurt, Germany. The C++ committee made a lot of progress on addressing national body comments on the full committee draft published last year, and is well on the way to publishing a second and final CD this winter with a final draft international standard a year after that. To meet that schedule, the committee decided to defer a major feature, “concepts”, and not include it in this standard.
I’m surprised at some of the commentary I’ve been reading on the web about the deferral of concepts, including not just technical inaccuracies but also that their absence in C++0x is somehow a big deal for C++ as a language or is a major geopolitical firestorm. It may feel like a big deal because of the work that’s gone into concepts and the large number of pages of standardese that were needed to specify the feature, and there was a lot of discussion about important design details including heavy traffic on the committee reflectors this spring and early summer that probably made them look more controversial than they are.
But my opinion is that concepts’ presence or absence in C++0x just won’t make much difference to most users. Let me give some reasons why I feel that’s so, and maybe debunk some common misconceptions along the way, in the form of an unofficial FAQ. Note that I was never involved in the design of concepts and don’t speak for the designers, whose views might differ here and there; the following are observations from my point of view as a participant in the standards body (including in Frankfurt last week), and chair of the ISO C++ committee during the entire time concepts were being developed up to the meeting they were voted into the ISO C++0x working draft last fall.
Q: Bjarne Stroustrup is the creator of C++ and a primary designer of concepts. What’s his take?
A: Great question. See Bjarne’s coverage here, published earlier today in Dr. Dobb’s.
Q: Were concepts removed because of political reason X, Y, or Z?
A: No. Concepts were removed because of normal project management considerations. The basic constraint has been phrased in many ways, all of them hitting at the same underlying tension among time, scope, cost, and quality. Here are two examples: “You can pick what goes on the train, or you can pick when the train leaves the station, but you can’t pick both.” “You can have good, fast, and cheap – pick any two.”
Fundamentally, the committee members felt that concepts are desirable but many (though not all) believed that they were still in design mode and needed more “bake time” – a formal poll of committee members in Frankfurt put the expected time at between three and four years – to get up to the quality of a feature that belongs in an international standard. Therefore, the two major options, and the ones that people generally argued for, were to either:
- Prioritize (bigger) scope. Wait for concepts, and accept a delay to the rest of the standard including features that are already finalized and ready to ship.
- Prioritize (faster) schedule. Finish and ship the standard to get already-done features into users’ hands, and decouple concepts to continue work on them for a future standard.
The committee decided to prioritize schedule and ship C++0x sooner while still leaving the door wide open to also adopt concepts later.
Q: Isn’t removing concepts a lot of work? Concepts are used pervasively in the C++0x CD published last fall.
A: Yes, but it’s less work than you’d think. We won’t have a de-conceptized working draft for the post-meeting mailing, two weeks after the meeting, but should have one soon after that. (I would be remiss not to add: Thanks to our always-hardworking project editor, Pete Becker!)
Recall that, until last September, we had a complete draft of C++0x features specified entirely without the use of concepts. And many of the uses of concepts in the draft standard library were just replacements of preexisting non-concepts wording or implicit requirements (e.g., DefaultConstructible, MemberContainer), and will just revert to their previous wording or disappear back into implicitness.
The main C++0x feature that was always specified in terms of concepts was the new range-based for loop (e.g., for( x : collection ) ). I’ve seen some wonder what we’ll do about that, but it’s already done; the non-concepts text for that feature was already voted in at the same Frankfurt meeting.
Q: Wasn’t this C++0x’s one big feature?
A: No. Concepts would be great, but for most users, the presence or absence of concepts will make no difference to their experience with C++0x except for quality of error messages (see below).
C++0x is still a major revision with many new major features, including improvements to templates (e.g., variadic templates, template aliases). C++’s other major new features include lambda functions (which unfortunately for Java were rejected for Java 7), move semantics (aka rvalue references), a concurrency memory model, threading and atomics libraries, initializer lists, and more. Other handy new features include delegating constructors, inherited constructors, defaulted and deleted functions, explicit virtual overriding control, alignment support, static assertions, and more. Not to mention convenience features like range-based for loops and “auto” type inference that are small but will certainly get a lot of use (as they do in C# and Java).
A number of those features are available now or soon in real compilers, including Gnu gcc, Visual C++ 2010, and Intel C++.
Q: Aren’t concepts about adding major new expressive power to the language, and so enable major new kinds of programs or programming styles?
A: Not really. Concepts are almost entirely about getting better error messages.
Yes, concepts would add one truly new expressive capability to the language, namely the ability to overload on concepts. That’s inconvenient to simulate without language support. Concept-based overloading would have been used in a handful of places in the standard library. But that’s it.
By far the most visible benefit of concepts lies in clearer template error messages, including the ability to do separate checking – confirming that a template’s implementation type-checks correctly with all possible valid types without having to instantiate it, and confirming that a given type can be used to instantiate a template without knowing the template’s implementation.
Q: Weren’t concepts all about bringing templates into the 21st century? Where does this leave templates?
A: Templates are still king of the genericity hill, for all their faults in the area of opaque compiler messages.
It’s important to remember that, in 1994, C++ was the only major language whose type genericity capabilities were strong enough to create the Standard Template Library (STL). Today, 15 years later, that is still true; you can’t express the STL’s containers-algorithms design separation well, or at all, using generics facilities in Ada, Java, .NET, or any other significant commercial or research language that I know of; as we learned when doing STL.NET, you can do the containers well with other generics, but not the orthogonalization with algorithms that is the heart of STL design style. Concepts or not, that hasn’t changed.
So my personal view is that templates have been in the 21st century since about 1994. No other language has yet caught up to their expressive power. And C++0x is adding some further power to templates, in particular by adding variadic templates and template aliases, both of which will help to simplify template code.
Is Boost using its concepts library in the other libraries?
(I assume that the not in “C++ is *not* an object oriented language” is a typo and you actually meant “C++ is an object oriented language”.)
I am not saying that C++ is not OO because templates aren’t. What I meant to say is that the design of templates, as a language feature, lacks encapsulation: the operations that must be implemented by a template parameter are implicit in the implementation (!) of the template itself.
I agree that templates achieve “compile-time duck typing”, a flavour that is safer (if less flexible) than Python’s (see also http://en.wikipedia.org/wiki/Duck_typing, section “Templates or generic types”)
Concepts do not constrain template’s duck typing beyond what static typing already does, they just declare outside the template what the template needs from its parameters and, by doing so, can help the compiler pointing out errors with greater precision.
Poor error messages increase the cost (and the frustrations) of developing a piece of software.
It goes without saying that having a compiler that points out errors in your code (close to the location of the problem!) is better than having to rely on the documentation alone or having to decipher the instantiation “haystack”.
C++ is not an object oriented language. Templates don’t try to be object oriented. This is not a bad thing.
Your analysis of template debugging is all kinds of faulty: you don’t have to look at source for a function to figure out it’s use – check the documentation.
Also, as many have commented on, templates achieve something similar to python’s duck typing. In my experience I have the same kind of problems, but the last conclusion I would draw is that python is not object oriented because of it. Good code/templates should be written such that it’s “easy to use correctly, and hard to use incorrectly.”
When code that uses a templatized library does not compile the error you get is what some people call the “instantiation stack”.
This kind of wording painfully points to the fact that templates are a non-object oriented feature of an object oriented language: you need to look at the internals of a templatized library in order to provide a type that compiles.
It’s the same as saying that you have to look at the internals of a function to figure out its signature.
For me it is very regretful that this issue is not going to be addressed in what is now C++1x.
@Nicol Bolas
@Doug Gregor
Quoting the current status quo back to me seems to miss my point – which is that the status quo probably needs to change.
I reiterate that if something can’t see the light of day inside of 13 years (Concepts and Modules), it’s either very wrong or wasn’t worked on long enough. Assuming it’s the latter because Bjarne (and Herb?) still believe Concepts should be in C++ then the problem is likely to be with (as people keep reminding me like I didn’t know :)) the volunteer nature of the committee and the lack of resources to do anything different.
In that light it can’t be remiss to suggest solutions to that. Mine was that Bjarne, Herb, and some other appropriate committee members consider pushing to get a full time, paid, non volunteer effort together so that Concepts and Modules etc. can see the light of day before I am a very old man!
I see no reason why Microsoft and Apple or Whoever etc. can’t sponsor (not own) that effort (with money from STL.NET etc. lol) and make a clear commitment to implement the results (unlike with Attributes apparently?) without doing so in a way that invokes the wrath of God that Nicol describes.
C++ can and does make money when effort goes into the features people want and when they get them in a standards based way.
I’d love to hear other ideas on how we might improve things rather than just state the status quo.
IMHO we have to ask again if we are missing some kind of commercial reality if it takes 13 years to mature an idea that still doesn’t see the light of day? In that time frame C# and .NET came from nowhere to cleaning up the market. So in that context if these features need more time then we should be asking the committee to find a way to put it in and in a way that gets us these features before we die and C++ does.
The volunteer route is just not delivering fast enough IMHO. That is not to say they aren’t working hard enough. We just need to clone them! Maybe the committee should work on that latter idea actually? ;).
I am not laying any blame on anyone for the ‘failure’ of Concepts. I don’t even claim to know if Concepts are a good thing (though they look good). I just do claim that there are some great C++ features like Modules, Concepts, and open multi-methods on the horizon that could get here a lot sooner than they apparently will if we just ring our hands and accept the status quo without a fight.
A number of people have asked why I focused on error messages, when concepts do have other benefits such as separate checking and the ability to say what you mean when writing templates.
That’s because I was focusing on: (a) the most visible effects, not just the most important underlying reasons; and (b) the point of view of a typical C++ programmer, who consumes template libraries much more often than authoring them (most people I teach say they have never done the latter, and the most frequent questions I get in class exercises that ask attendees to write a template are about what the syntax is and how to use template parameters in the body of the template).
As I put it above (emphasis added): “… for most users, the presence or absence of concepts will make no difference to their experience with C++0x except for quality of error messages… By far the most visible benefit of concepts lies in clearer template error messages, including the ability to do separate checking…”
Note that I included the ability to express constraints in code and do separate checking among the reasons/sources behind the end result of better diagnostics. Most C++ programmers aren’t authoring templates, and so wouldn’t be writing “requires” etc. For them, the primary effect concepts would have would be better (earlier and clearer) diagnostics, for all of the underlying reasons that posters have mentioned.
The C++ committee cannot “push” any particular feature, because it has no resources to commit to the development of a feature. Modules were moved to a TR because no volunteers stepped forward to develop an implementation and specification for the feature, while Concepts did have volunteers working on both.
It’s true that templates don’t *need* a type system. But then, neither does the rest of the language. We could all be programming with Python or some other fully-dynamic language. Despite the fact that I’m a great fan of Python, I find it much less usable, practically speaking, than C++ is once a program gets even to moderate size. Why is that? It’s because the explicit declarations of types and other statically-checkable features of my program are essential for creating modularity (a.k.a. the ability to modify one part of my program without breaking all the others).
I’m sure some fraction of what academics do with language theory is purely cerebral and makes no difference to ordinary programmers, but don’t dismiss it just because someone used the word “theory.” For the most part, the focus of language theoreticians is driven by real needs of programmers in science and industry, and in the end, a language’s “theoretical background” has practical implications for real programmers trying to get something done.
“What concepts are about” is a completely subjective question, and I am sure that even among those actually working on concepts you’ll find a wide range of opinions. That said, I don’t think anyone who’s been deeply involved with the feature would agree with Herb’s assessment that they’re “almost entirely about getting better error messages.” For me, for what it’s worth, they’re about modularity, about being able to express what I mean in code, and about making generic programming accessible to people without PhDs in (or maybe just with an aversion to) stupid template hackery.
Anyway, just to throw my own take in the ring, there’s more on what went down in Frankfurt at http://cpp-next.com/archive/2009/08/what-happened-in-frankfurt.
You seem to have a problem with understanding the difference between the C++ specification and, for example, Visual Studio. These are not the same thing; they are only barely related to each other.
Visual Studio is a product by Microsoft. C++ is an ISO specification that is maintained by a working group of volunteers. Visual Studio *implements* C++, but it is not C++. In order for there to be a “conceptualised, Lambdafied, Modularised” Visual Studio 2005, there would have had to be a C++ specification with these features in it released in 2003 at the latest in order for Microsoft to implement all of these features.
It should also be pointed out that VS is, even now, not ISO C++03 compliant. And I’m not just talking about misfeatures like “export”. So when would Microsoft get to implementing concepts, lambda, and modules? Whenever they felt like it.
Now, if Microsoft so decided, they could have *created* a compiler for a C++-like language that was “conceptualised, Lambdafied, Modularised”. But it would not have been ISO Standard C++. And any new standard that implemented those features would likely implement them differently, thus creating incompatibilities.
Also, the FSF-brigade would have been screaming bloody murder, with talks of “embrace, extend, extinguish” and such.
Canceling STL.NET will do nothing for getting us Modules one day sooner. Bjarne, Edge, and Microsoft do not control C++. The C++ Working Group does. And money doesn’t make them work faster.
If there’s one thing the failure of Concepts tells us though, is that if something isn’t working out, cut it ASAP. If the WG had been pushing Modules instead of Concepts, *those* would have worked out (Modules are simpler than Concepts). Instead, Modules was bumped for later, and we still failed to get Concepts.
@Glen: I agree with most of the points you mentioned but those seems to be just dreams.
I feel so disappointed.
@Nicol Bolas:
1: I have to disagree with you. Providing theoretical background is not just nice but it helps the programmer to have better understanding of the problems and solutions that definitely result in much more quality in the finished work. I really hate to see some programmers just want the get the work done. The result is obviously as low quality as what we can see in lots of weak softwares available these days.
Also I have to disagree with folks who think the main use of concepts is about the error messages. IMHO quality of error messages is one of the results of the theoretical background of templates that makes the templates more rational.
And I can’t guess why Herb just mentioned the error quality as the only reason for concepts too!
Some points:
– About Lisp macros. Those are different and more powerfull beasts. We shouldn’t really compare those to C++ templates, but if you really want, then to me the most interesting part is that they’re not strictly compile time. C++ went towards static everything, that made sense 15 years ago, not now. We’re at a point where C++ is so static that we don’t have good modules, our code takes ages to compile and link, we can’t hot-reload code… And the usual excuse that C++ cares about performance is totally untrue, again, it was 15 years ago, but today? No alignment, no threads, no SIMD, some will come, but too late. Templates statically generate code, way too much, they actually make things slower if you don’t take care.
– About templates being 21th century. Yes, maybe templates are very powerful, still less powerful than Lisp, but if you want not to regard lisp as mainstream… Fine. Still most of their power is impossible to use. You can make boost::lambda, but do you want to use it? With all those incomprehensible errors? Suffice to say, I develop games on PS3, 360, PC, PSP etc… No two compilers will compile the same template code. You make one compiler compile, then the other 99% of the times, if the templates are any sophisticated, won’t. Now to me one thing is clear. If you make a standard so ugly that even C++ compilers, after years, can’t get it totally right, then you’ve really made an ugly, ugly, ugly mess. Template’s power is evil.
– C# collections… They’re sane. They’re threadsafe. They have interfaces, so you can actually use them publicly, without having to expose everything, and without needing to wrap your stuff in getters and setters. STL. Yes you have algorithms, but you can use them only privately, because publicly you don’t want to expose STL containers directly, you have to wrap them, and then algorithms are no usable anymore. C# does not have algorithms? What about LINQ? PLINQ? Way powerful, on collections.
I’m surprised by this article
@Nicol Bolas
Nicol, if you re-read my post you will see that I am aware the team is volunteer, I actually say that in my post.
Your comment that:
‘You seem to be operating under the belief that the C++ Working Group is an organization who’s members spend their days doing nothing but thinking about and working on the C++ specification. This is simply not true.’
seems to be missing exactly the point I was trying to make which is it is exactly because the C++ Working Group clearly does not as you say ‘spend their days doing nothing but thinking about working on the C++ specification’ that I believe we have a problem.
If they did work full time on it, maybe it wouldn’t be 13 years, as we are now hearing, to get an acceptable Concepts proposal together. We still have no Modules or any of the other things that I mentioned in my post either. But maybe someone just needs to blog more about that?
I don’t think it’s wrong to suggest if a full time team could address this situation quicker than what we have today. I never said it would be easy or likely, just that it might be necessary and a way it might happen. Surely there has to be a way to better the situation we have now.
C# has had a dedicated full time commercial team and it shows. C++ does not and it also shows. If we had had a full time team earlier then maybe VS2005 even could have been a conceptualised, Lambdafied, Modularised C++. It didn’t happen because people were working on other things (like STL.NET) which I doubt will ever get used.
MS dropped the ball so badly with C++ that they had to buy EDG technology to catch up (a good thing) and it was a similar story for MFC. One could even speculate that we only got Lambdas so quickly because it fitted in with the Concurrency agenda MS is following. In VS2010, I can’t even use nullptr still in standard C++, and how hard is that to implement or agree on sooner??!!
Even if there was no full time team, better coordination and less distraction with things that people are not asking for would benefit the community as a whole. For example, if I was Herb, I’d suggest MS cancel the STL.NET project (sorry to pick on it) now (maybe they have?) and use that money and those people to work on Modules with Bjarne and EDG. I am sure there are other examples people can think of. Of course by then we will all have solid state drives (or even flying cars? ha ha) and maybe it wont matter after all… :)
Anyway, nobody doubts these are all great amazingly talented (and humble) people, I just want to see the fruits of their work sooner and more unified, that’s all. If we can kick up enough debate on this, maybe they’ll find a way. I can wish at least can‘t I? :)
1: The theoretical background of C++’s templates means nothing to a programmer trying to get something done. Providing a theoretical background is nice and all, but I’d rather the WG spend their time on features that actually *do* something.
2: Templates don’t *need* a type system. That’s the whole idea behind templates. Concepts only gave them one to make it easier to specify constraints.
Herb only highlighted error messages because that’s the main use for them. The other stuff is not a necessity.
@Glen
You seem to be operating under the belief that the C++ Working Group is an organization who’s members spend their days doing nothing but thinking about and working on the C++ specification. This is simply not true.
The C++ Working Group is a *volunteer* organization. There is no “being fired” because nobody hired them in the first place. It exists as a collective of people who want to improve C++ and submit a specification for ISO approval. That is all.
The reason that languages like C# evolve faster is because Microsoft hires people for the sole purpose of evolving their language. C++ is governed by a volunteer organization.
“A bolder attitude to using keywords.”
Backwards compatibility is why a lot of people use C++ to begin with. If you start making already compiling code break just because you were not willing to take some time to choose a less conflicting keyword, then you don’t deserve users. Even C#, for example, overloaded the keyword “delegate” in their implementation of lambda instead of using a keyword like “lambda” or “unnamed”.
Judging by their retrograde coding standard, Google would not be interested. I’d pin my hopes on Adobe.
I’m surprised that no one has mentioned here that Boost implements the functionality of ‘concepts’ at the library level. As a stop-gap, you can use Boost’s (ugly) library as an alternative to real language-support.
I agree with you. However, there is always too much politics in our profession. MS is always insisting that it customers move on to C#. They haven’t paid proper attention to the Visual C++ project for years.
Herb, I would like to express the ignorant opinions of a lay person who used to use C++ but who now has to use C# because Microsoft’s C++ story evolved too slowly. What upsets me is that the C++ committee seems to be doing the same.
I have enormous respect for all the people involved in C++0x, but IMHO not having Concepts is a major screw up. It’s hard to pin the blame on anybody so in that case I just think we have to blame everybody for now until the situation is fixed.
IMHO C++ is suffering because of a collective lack of will and organisation by the committees strongest members to simply do the right things for C++ in a timely fashion. This has been hurting the customers that use C++ for some time. Microsofts own forums for C++ generate almost hate mail type responses these days that reflects that the situation is as bad as I suggest. Doing all the right things on your own is the wrong thing customers are saying.
In the time we could have had a great standard C++0x we instead have a PPL, a TBB, a C#, a C++/CLI, an STL.NET etc. etc, but not yet the C++ that most people appear to be asking for. So many distractions exist for no good reason. For example, STL.NET will never fly as managed C++ prior to C++/CLI was never going to fly. Who ever asked for those?
Herb says we can have any two of good, fast, and cheap. But why say that?! MS and Google are not short of money or talent and they both use C++ a lot so I see no good reason (other than political or poor community organisation) for not being able to have a good, fast and expensive C++! C++ appears to be in need of a clear focused C++ development team at this point, not just a committee.
Because if Concepts took 5-7 years so far, and the committee says it’ll take another 5 years to appear then that’s 13 years! If this is for real, you should all fire yourselves now or get a better plan because that’s just a crazy amount of time to do anything! It’s just not commercial or necessary to work in these timeframes and the drop off in the popularity/credibility of C++ in the market reflects these facts surely?
Anyway, my plan is not to fire you because you are all voluntary after all! So the plan is in fact to hire you!! All of you. Here’s the plan:
* MS, Google and Apple please put a few million ‘in the kitty’ for C++. You use it and you can afford it. And we like it and want to use it in more places and with more productivity.
* Ship C++0x today, but minus Concepts and Attributes. MS abuses attributes in the C# space all the time, I am sure the C++ world will do the same if given the chance.
* Get a Globe Trotter style C++ development dream team together that contains the greatest minds pf C++ focused on and prioritised by what customers actually want and don’t work on anything else until that spec is thrashed out completely.
* The kitty can pay for the dream team. My choices are: Bjarne, Herb, Lawrence, and Andrei (of Elements in programming fame) and who ever else that team wants to enlist themselves but someone from Clang, EDG. and Apple would be nice. That kind of team will have all the moral authority and combined commercial power to define the de-facto standard the second the results are published.
* Enough work has been done already on the important areas, that if there are no distractions, lots of coffee, and you all work together full time, face to face, then surely the team should be able to publish a definitive work in months not years (read less than one year)?
For me, this work should produce a C++ containing:
* Concepts perfected.
* A definitive language specification for MODULES!
* Open multi-methods. Don’t let this become the next Concepts dragging on for 5 years from now, do it now!
* Attributes (if you insist). But one that Microsoft WILL actually implement (?) and that doesn’t use double brackets, one is enough ;)
* C++/CLI’s override and method rename mechanism – further reunification here would have been nice? Why not? Why the resorting to attributes here?
* A bolder attitude to using keywords. If you are trying to simplify the language and its error messages then why obscure it again with strange hard to read attributes and re-using of old keywords in odd places. How about specifying in the standard a list of keywords you might use in the future and issue warnings about them now to pave the way in the future…
* Park the evolution of iterators. Ranges are definitely the way to go. Lets have them now in this standard.
* A far bolder set of standard Attributes and compiler directives for things like unused parameters, variables, multi inclusion guards, optimisation hints etc. etc.
There appears to be some big improvements in C++ IDEs and compiler technology on the way in the next few years from MS/EDG/Clang etc. so nailing the definitions of some big advances in the language design now would be a great way to revive C++’s status and ensure we get ALL of these things inside of 2 years, not 5 years.
In concusion: 5 years is too long for us to wait for these features. We should have had them yesterday!
Ok, phew, that’s it! I’d love to read some other peoples opinions here and hope this kicks up even more hard arguments and friendly but passionate discussions and gets the committee revisting its ideas so we don’t get what feels like failure, but instead get an even bigger bolder and quicker plan!
I’m still groping around with the concept of “Concepts,” although Stepanov’s recent book (highly recommended, even for mathematical ignoramuses like me) helps.
As far as I can see, they’re inappropriate for the task of simplifying error messages in template instantiations. What, you need implicit and explicit? And “concept maps”? And all the usual C++ baggage of overriding and scope and such-like? I think I’ll take my three thousand word compiler dissertation which boils down to “You screwed up,” thanks very much.
I do think they’re an enticing idea, though; if only because they seem to embed set theory into the C++ type system. This has got to make libraries more robust and more usable. I don’t get to work much with mathematical libraries (more’s the pity), but I have spent quite a lot of time working with large-scale concurrency issues — and I’m pretty damn sure that concepts would help me build and analyse a far better solution than I could with even C++1x.
@AP: We’ve gotten by without 1 and 2 so far though. Generic programming in C++ is already far more advanced than in Haskell, so the theoretical underpinning obviously isn’t a complete show-stopper. Concepts would have been nice for those reasons, but they’re not “needed”.
@James Slaughter: The main reason why concepts could have cleaned up error messages is because they provide a mechanism for detecting the error at the instantiation site, rather than inside the instantiated template. That would have been a pretty major improvement, and pretty much orthogonal to cleaning up the error messages in general.
Catching errors earlier have little to do with how the compiler prints out and formats those errors.
I was never sold on the better error messages part of the concepts deal. I didn’t trust compilers to do a better job of telling me that “You can’t call A because B doesn’t map to concept C due to not having function D” than they’ve done in the past, especially when A is overloaded on different Cs and D is potentially an overloaded name in scopes accessible via B. Admittedly, the instantiation stacks were likely to be shallower, but it all seemed like hand-waving and wishful thinking.
I’m also convinced that implementations could do a service to users by filtering their own messages before they spit them at the users, and that this doesn’t require concepts. For example, there are implementations that automatically invoke STLFilt. It would be commendable if Visual C++ followed suit, but I guess the fact that it hasn’t done so indicates a relative lack of demand for better error messages anyway…?
I predict that strategic use of constexpr and static_assert will do more for compile time diagnostics than concepts ever would. Having said that, concepts were compelling for other reasons, and though I agree with the decision that’s been made, I look forward to seeing them in future.
Regards,
James.
How will this affect VS2010?
7 years after my first publication of the GluCat library, I am still looking for a sensible way for C++ to mimic the relationship between different mathematical constructs. In the case of GluCat, the main template class is numeric, and is intended to take a template parameter which is a numeric type such as float, double, etc. The template class then provides a numeric type which is just like float, double, etc. – except that multiplication is not commutative. Concepts *could* have provided a mechanism for Glucat to flag to other template libraries that the multiplication that it provides is *not* commutative; and concepts *could* have provided a mechanism for GluCat to require that its numeric template parameter class provides a multiplication which *is* commutative. I still can’t see a clear way of doing this in C++ 1998. It now looks like I needn’t bother with C++1X, as it won’t even try to provide a solution.
P.S. One should also not forget the code bloat that results from template instantiations and the effect it may have on the size of one’s working set and thus ultimately performance.
I’d also like to point out that while LISP may not be able to do as much as C++ at compile time, that isn’t the only way to good performance. It may help you catch errors earlier (which is definitely a good thing) but the issues about whether something happens at compile time (i.e., front-end compile), JIT-time (i.e., back-end compile), or runtime are really orthogonal to whatever actual performance the entire process (from load to unload) exhibits (and even the time taken to compile should be considered as a cost [albeit with a smaller weight than run time in most cases]).
Also, Haskell’s type system is arguably even more advanced than C++’s and thus should be able to provide the [expressibility] benefits of LISP with the [perceived and often assumed rather than measured] performance of C++.
Good job. But I think you might agree, it’s not the prettiest thing.
@Trey, you are right; you _could_ do it. My point is only that it generally isn’t.
I’ve seen a statically typed scheme extension; in PLT i think. Maybe it’s done there
@David, The improvements in C++0x and VC10 is certainly exciting, but I’m not sure it’s reached “most expressive”. MPL and its ilk is impressive; not because of its expressiveness, but rather that it’s even possible.
crap…
“call” templatizes on: typename FuncDecl, typename C
MakeFnDecl on: typename iterator
and MakeFnDecl is instantiated with IntVec::const_iterator for “call”.
Everything else should be fairly clear.
“I challenge a C++ developer to show me an instance where they passed “std::search” as an argument to a function call […]”
I like a challenge!
template
typename FuncDecl::Result call(C const& container, typename FuncDecl::Fn function)
{
return function(container.begin(), container.end(),
container.begin(), container.end());
}
template
struct MakeFnDecl
{
typedef iterator Result;
typedef iterator (*Fn) (iterator, iterator, iterator, iterator);
// simplified std::search decl
};
#include
#include
#include
int main()
{
typedef std::vector IntVec;
IntVec ints;
ints.push_back(10);
std::cout << *call< MakeFnDecl >(ints, &std::search);
return 0;
}
I tried to keep it as simple as possible while also showing that basically all of those things could be templatized/delayed at various points. Most importantly MakeFnDecl could be declared and deduced in a more meaningful place.
Definitely not easy though, and obviously the designer has to have exactly this consideration in mind.
…PS: Thanks for the insightful (as always) post on the dropping of Concepts Herb! It’s definitely a loss, but it’s managable, and we still get cool stuff.
PPS: oh man i hope (read “doubt”) the formating doesn’t destroy this code
I have to disagree with Herb’s post. Concepts are needed in C++ for much more than *pretty error messages*. Concepts are to C++ what typeclasses are to Haskell – in that they are fundamental for generic programming in C++.(For those unfamiliar with typeclasses – see: A comparison of c++ concepts and haskell type classes http://portal.acm.org/citation.cfm?id=1411324 for a comparison.)
Concepts are required for at least the following purposes: 1) To put the generic programming features of C++ on a solid theoretical background 2) To provide a type system for templates 3) To simplify error messages. (Admitted 1 and 2 are closely related.) I am certain Herb knows all this, but I cannot guess why he chose to highlight reason 3 as the only reason for adding concepts to C++
Highly Recommended reading:
A comment from Jeremy Siek, one of the co-authors of the C++ Concepts proposal:
“Sad day”
http://lambda-the-ultimate.org/node/3518#comment-50071
“While the Concepts proposal was not perfect (can any extension to C++ really ever be perfect?), it would have provided a very usable and helpful extension to the language, an extension that would drastically reduce the infamous error messages that current users of template libraries are plagued with.
It is a real shame that disagreement over what I viewed as an uncontroversial design point turned into the sticking point. […]”
In Bjarne’s words ( http://www.ddj.com/article/printableArticle.jhtml?articleID=218600111&dept_url=/cpp/ ):
” […] this was a big disappointment for those of us who have worked on concepts for years and are aware of their potential […]”
“At the July 2009 Frankfurt meeting of the ISO C++ Standards Committee (WG21), the “concepts” mechanism for specifying requirements for template arguments was “decoupled” (my less-diplomatic phrase was “yanked out”). That is, “concepts” will not be in C++0x or its standard library. That — in my opinion — is a major setback for C++, but not a disaster.”
“I and others preferred the first alternative (“fix and ship”) and considered it feasible. However, a large majority of the committee disagreed and chose the second alternative (“yank and ship,” renaming it “decoupling”).”
“Surprisingly (maybe), there were no technical presentations and discussions about “concepts” in Frankfurt. The discussion focused on timing and my impression is that the vote was decided primarily on timing concerns.”
Here come the managers!
“Today, 15 years later, that is still true; you can’t express the STL’s containers-algorithms design separation well, or at all, using generics facilities in Ada, Java, .NET, or any other significant commercial or research language that I know of”
Although you may be simply pointing out the problems with generics, I’d like to point out there are other languages which have templates. The D programming language (http://www.digitalmars.com/d/), even has template constraints, which serve a similar purpose to concepts. They’ve enabled simpler and more flexible functions. (e.g. the std.algorithm library: http://www.digitalmars.com/d/2.0/phobos/std_algorithm.html)
Great report, Herb. I’ve been away from C++ for a couple of years, but I enjoy following up the improvements to the next version of the C++ Standard.
Thing is, C++ people tend to care whether the language figures things out at compile time or runtime. This is largely a cultural matter. C++ is a descendant of C, which was in part designed to write Unix in. Any systems implementation language has to be efficient. Lisp, on the other hand, was designed with little regard for efficiency, although some implementations have produced very efficient code. We tend to disregard efficiency on the desktop, but it’s very important for servers and some forms of scientific computing.
The big advantage C++ templates have over Common Lisp macros is that C++ type information is available at compile time. The big advantage C++ templates have over the Common Lisp Object System is that they’re all done at compile time instead of runtime. (The big disadvantage, of course, is that C++ templates are nowhere near as elegant as either of those Common Lisp features.)
C++ templates are therefore still the most versatile processing available at compile time, and this is still quite valuable.
I’m a bit confused over the distinction you draw between CL macros and the compile time type analysis provided in C++.
Strictly speaking, you may be right (that CL can’t do what C++ does at compile time). As a user of languages, what do I care if the language figures things out at compile time or at runtime?
Looking at the selection of libraries boost provides, nearly all of them are either already provided/trivial in CL, or completely unnecessary. And while I admire the technical skills of the boost community, they’ve had to work *really* hard to provide the basic functionality found in CL (and many many other languages).
Regarding iterators and the data structure/algorithm separation provided by STL. That is certainly one way to solve the problem. CL approached the problem with a different solution, you can still define new types and register them appropriately such that they will blend in seamlessly with all the expected routines: setf, sort, merge, map, whatever…
Re Common Lisp macros — macros are similar in many ways to function or class templates, in the sense that they generate implementations of algorithms or data structures and are parameterized over structured data. (of course, by macros, I mean Lisp macros — not the broken things in C/C++).
Granted, I don’t have much experience; however, I’m not aware in any Lisp of a protocol for macros to deduce information based on the compile-time type of its arguments. no problem, you can always explicitly provide it — you could write a macro “map” that works over any sequence type, provided a “sequence traits” parameter that, for instance, specifies how to iterate forward and such. You could — but who has? I don’t mean just “iterate” — what about find, search, partition, sort!
Common Lisp excels in some other ways — it’s easier to pass parameterized functions around since static type deduction need not be performed on its arguments. I challenge a C++ developer to show me an instance where they passed “std::search” as an argument to a function call — you can’t easily, because static type deduction can’t be performed yet, and function templates are not themselves objects. This is a big sore point in C++. CL, with its dynamic typing practice, doesn’t need to perform type deduction on function arguments — it can be done at runtime or, with a sufficiently powerful optimizer, it can be _deferred_ until the point of call.
I would be interested in seeing a higher-order-macro based STL analogy. Perhaps calling “std::sort”, you pass an ordering-predicate-macro ^_^. It would definitely be unique. But I don’t think it would be usable. Even in CL, you really want functions, not macros, and you cannot pass macros as function arguments.
Thanks for the interesting thought experiment though. I think I’ll be pondering this one for a while.
Quote:
“So my personal view is that templates have been in the 21st century since about 1994. No other language has yet caught up to their expressive power.”
How are C++ templates more expressive than say Common Lisp macros, where code can be manipulated arbitrarily at compile time to create new syntactic elements at a whim?