Draft FAQ: Why do C ++ standards come out every three years?
WG21 has a strict schedule (see P1000 ) for standard release every three years. And no delays.
During each cycle, we regularly receive questions “Why is it so strict?”, Especially from new members of the committee who are not familiar with its history and the reasons for the current state of things. And during a preliminary teleconference with the Cologne administration, several people recommended describing why we were doing this and how the decision was made to adopt this schedule.
I painted all this in the form of questions and answers for the next draft of P1000, and sent a copy to the committee members on their way to Cologne. This material will be published in the next public version of P1000, we will send it in a few weeks starting from the current moment.
However, the draft FAQ may be of interest to the public, so I offer you a copy of it. I hope that for the most part it will be useful to you, enlighten in some ways, and perhaps even entertain a bit.
There are bugs in the standard, should you postpone C ++ 20?
Of course yes and no.
We are moving in a given direction at a chosen speed: bug fixes are planned for this last year, so the schedule in early C ++ “19” (Kona) sets a deadline for stopping the feature addition (feature freeze) in C ++ “20”, so that we had a year to fix bugs, including working with comments from different countries this summer. Before the beginning of 2020 (meetings in Cologne, Belfast and Prague), we must give feedback and apply any other solutions to problems, as well as bug fixes.
If we have one or two more meetings, then we could add a <feature name>, which is almost ready, so should you postpone C ++ 20?
Of course yes and no.
Wait for a couple more meetings to take place (after Prague), and C ++ 23 will be open for business, and first of all we will vote for adding <feature name> to the working draft of C ++ 23. This is what we did with the concepts: they were not ready for the transition from TS directly to C ++ 17. Therefore, at the first meeting on C ++ 20 (in Toronto), they voted to transfer the basic functionality of concepts to the draft C ++ 20, which gave a lot of time to improve and refine the rest of the contradictory part of TS (non-“template” syntax), which was introduced next year (San Diego). Now all the functionality is ready.
This seems to be too strict. Why release IS releases at fixed intervals (three years)?
Because in the case of the release of C ++ IS, this is one of the two main options for project management, and experience shows that this option is better than the second.
What are the two options for project management for the release of C ++ IS?
Glad you asked.
In the case of a release, there are two main options: choose a feature or a release date, and when you select one, you lose control over the definition of the other. You cannot simultaneously control both. In short:
|If we control it||We will stop controlling it||Can we work on “big” multi-year features?||When do we add features to the IS draft?||What do we do if we find problems with added features?|
|“What”: features that we ship||“When”: release date.||Yes, in the documents with the proposals and the draft IS.||Usually earlier to conduct more integration tests → the average stability of the working draft is reduced.||We delay the release of the standard.|
|When: Release Date||“What”: features that we ship||Yes, in documents with offers and "feature branches" in TS.||Usually later, when the feature is better worked out → the average stability of the working draft increases.||We remove the feature, later we can add it again if it is ready by the time the next IS train is sent.|
(1) “What”: we select features and ship as ready, no need to choose a release time . If it turns out that you need more time to finalize a feature from the draft standard, then the whole world will have to wait for you. You work on big features that require several years of development, and then you try to stop working on new features at all while stabilizing the release.
So it was with C ++ 98 (it was expected around 1994, Björn said that if the release did not come out by then it would be a failure) with C ++ 11 (it was called 0x because x was expected by 2007 ) This is an “leave the patient unshielded” approach for an indefinite period, which led to a delay in integration testing and release. And this, in turn, led to great uncertainty in the market regarding the timing of the next standard, and whether it will be released at all (yes, not only the development participants, but even some committee members seriously doubted in 1996 and 2009, will appear are there any relevant releases). For several years, most compilers did not comply with the standard, because no one knew how many incompatible changes the committee would roll out in the new release, or when to wait for him at all? This has led to a wide variety and fragmentation of C ++ support in compilers available to the community.
Why did we do this, are we idiots? Not really, they were just inexperienced and ... let's say, "optimistic." It was a road paved with best intentions. In 1994-1996 and in 2007-2009 we really believed that we would now move another one, two or three meetings, and we would do everything, and each time they would be postponed for up to four years. And now they have seen from their own experience that there can be no transfer for a year or two.
Fortunately, everything has changed thanks to option (2).
(2) “When”: select a release date and ship those features that are ready, you do not need to select a set of features. If it turns out that more time is needed to refine a feature from a draft standard, we discard it and ship what is ready. You can continue to work on large features, the creation of which takes time as for several releases, but do it in third-party "branches", adding them to the IS master branch as soon as you can. And you constantly work on features, because their development is completely separate from the current release (there is no big connection point).
We have been adhering to this approach since 2012 and do not want to abandon it. This is the “regularly patching up the patient” approach, which leads to the expectation of higher quality due to forced regular integrations and the refusal to add work to the IS draft until it reaches a certain level of stability, usually within the feature branch. It also creates a predictable release cycle that the market can rely on. Over the years, authors of compilers began earlier and earlier, after the next release, to release versions of their products conforming to the standard, which had never happened before. And in 2020, we expect the release of fully compliant implementations in one year with the release of the standard, which also never happened before. This is only for the benefit of the entire market - developers, users, teachers.
And also note that since we began to adhere to this approach, we have begun to do more (if measured by large, medium and small features) and with higher quality (if measured by a strict reduction in the number of bug reports and comments on drafts of each standard). Although we ship what we managed to prepare (and if we didn’t manage something, we don’t ship it).
How serious are you about approach (2)? If, according to an authoritative member of the committee, some big feature is “almost ready”, then you will be tempted to wait a bit, right?
Very seriously, and no.
We have statistics: in 2016 in Jacksonville, when we finally decided on features for C ++ 17, Björn Straustrup spoke at a plenary meeting with a proposal to include concepts in C ++ 17. When no consensus was reached, Straustrup was directly asked if he wanted to delay the release of C ++ 17 for a year in order to include concepts in it. Björn answered “no” without hesitation and evasion, and added that C ++ 17 without concepts was more important than C ++ 18 or C ++ 19 with concepts, although Straustrup had been working on them for about 15 years. The choice was this: (2) we release C ++ 17 without concepts, and then C ++ 20 with concepts (which we did), or (1) we rename C ++ 17 to C ++ 20, which is isomorphic (2) with the exception of skipping C ++ 17 and refusing to release what was already ready for C ++ 17.
What about the trade-off between (1) and (2)? Say, we usually adhere to (2), but with “little” flexibility in terms to get “a little” extra time, if you need to refine the feature?
No, because it turns out (1).
Fred Brooks in The Mythical Man-Month popularly explained “the mythical little transference” and concluded: “ Do not allow any small transferences .”
Imagine we ported C ++ 20. We would have to go back from (2) to (1), no matter how hard we try to avoid it, and at the same time would not receive any benefits. If we decided to postpone C ++ 20 to polish it, then we would delay the standard for at least two years. There are no such concepts as the transfer of one or three meetings, because during this time others will continue (fairly) to say: "Well, my feature only needs one more meeting, we still rescheduled it, let's postpone another one." And if we transfer at least two years, it means that C ++ 20 becomes C ++ 22, and most likely C ++ 23 ... but we are already going to ship C ++ 23! - That is, in any case, we will ship C ++ 23, and the only difference is that we do notWe transfer C ++ 20 with a large amount of work done, ready for release, and do not make the whole world wait another three years. Delay will not benefit these features, most of them or all together.
Therefore, the sentence is equivalent to “let's turn C ++ 20 into C ++ 22 or C ++ 23”, and the simple answer to it: “yes, we will have C ++ 23, but in addition to C ++ 20, and not in his place. ” A C ++ 20 delay means skipping C ++ 20 instead of releasing a good, stable, finished product, and there will be no benefit from this.
But feature X is broken / it takes more time than we have left to fix bugs in C ++ 20!
No problem! We can just cut it.
In this case, someone will need to write a letter in EWG or LEWG (depending on the situation) with a description of the situation, and offer to remove the feature from the working draft IS. These groups will consider the appeal, and if they decide that the feature is broken (and the plenum agrees with them), then the feature will be postponed until the next C ++ release. We already did this with C ++ 0x concepts.
But in the case of (1), we will transfer not only this feature, but the entire set of features from C ++ 20 to C ++ 23! That would be ... bust.
Does approach (2) mean “major / minor” releases?
Not. At first we said this until we realized that (2) only means that you do not need to choose a set of features even from the point of view of the “main / secondary” release.
Approach (2) means only “we ship what is ready”. Releases are obtained:
- the same size (that is, usually average) for features is “smaller” because less time is spent on their development (say, less than three years each), and in general we get the same number of completed features in the release;
- and a variable size (it’s not necessary once or twice) for features “bigger”, which take more time (say, more than three years each), and each IS release includes as many of these features as they manage to complete for release. Therefore, in some releases there are more, in others less.
C ++ 14 and C ++ 17 were relatively small, because a lot of standardization effort was spent on long-playing features described in implementation proposals (for example, contracts) and “feature branches” in TS (for example, concepts).
C ++ 20 is a great release ...
Yes. C ++ 20 has many major features. Three of the largest begin with “ko” (concepts, contracts, coroutines), so we could call it co_cpp20. Or co_dependent.
... and is not too much done in the three-year cycle for C ++ 20?
No, see above "once at a time is not necessary."
C ++ 20 is big not because we have done more in three years, but because there are a lot of long developments (including at least two that we have been working on in the current form since 2012 in the form of P-sentences and TS-branches ) reached the stage of readiness and they decided to include them in the draft IS of the same release.
Almost always, the main features are developed for many years. The main difference between approach (1) for C ++ 98 and C ++ 11 and approach (2) is that in C ++ 98 and C ++ 11 the release was delayed until all these features were ready, and now we ship large as soon as ready, and along with them we will release much more.
C ++ 20 went through the same three-year cycle as C ++ 14 and C ++ 17. We have not done more in the last three years than in the previous two cycles, we just added more to the main features. If any of them were not ready, then we would have thrown it out and finished it already for C ++ 23. If this happens, we will report this in the implementation proposal and explain the reasons.
C ++ 14 + 17 + 20 made up our third nine-year cycle (2011-2020) after C ++ 98 (1989-1998) and C ++ 11 (2002-2011). But since we adhered to approach (2), we also released developments that were ready for the end of three-year and six-year cycles.
Isn’t it better to catch bugs when a product is under development, and not after it is released?
Of course better.
But if we are talking about the reasons for the delay in the release of the C ++ standard, then this question implies two false assumptions:
- that before the standard was released, features did not come out and were not used (for many, there is already experience in production);
- and that all features can be used together until the standard is released (not allowed).
- Most of the major features of C ++ 20 were implemented in the form in which they are reflected in the current draft of the standard in at least one compiler, and in most cases have already been used in production code (that is, they are already available for users who are very satisfied) . For example, coroutines (introduced just five months before this article) were used for two years in production at MSVC and one year at Clang, which was very pleased with large customers (for example, Azure and Facebook).
- We are not going to catch many problems of interaction between features until users start using them in production, that is, before the standard is released, because many developers will wait for it to be released in order to implement different projects. And if we show uncertainty about the timing of the release, then these implementations will also be delayed. Well, they still implement something, but much will be paused until the developers are sure that we are ready to release. Ask the creators of <favorite compiler name> what happened when they implemented <large feature name> before it appeared in the published standard. In many cases, it is necessary to implement repeatedly, and break off consumers repeatedly. Therefore, developers prefer to wait for the committee to approve certain features.
Finally, do not forget about the problem of interaction features. We not only release them when we are ready, after that we still need time to search for problems of interaction between features and to add support for such interactions, which we simply cannot find out before new features become widely used. And it does not matter how much we delay the release of the standard, there will always be interactions that we can explore only much later. You need to manage this risk with the help of flexible design, ensuring the compatibility of features, and not wait to get rid of all the risks.
The standard will never be perfect ... don't you release bugs?
If we see that the feature is not ready, then we must remove it from the release.
If we see that a feature can be better, and we know that the change may turn out to be backward compatible, then this is not a reason to refuse its release now. It can be released as an extension in the following C ++.
We intentionally release features that we plan to improve in the future, while we are confident that we can maintain backward compatibility.
But shouldn't you try to minimize release errors?
Yes. We are trying.
But we do not try to avoid all risks. There is also a risk and (possible) price of refusing to release what seems ready to us. And more often than not, we are right.
Are you sure that now the quality is better than using the approach (1)?
According to objective metrics, the volume of comments from different countries and bug reports, C ++ 14 and C ++ 17 were our most stable releases, and by these metrics they were 3-4 times higher than C ++ 98 and C ++ 11. And the reason is precisely in the regularity of releases, in placing large features first in TS branches (including full descriptions of their integration with the main standard) and in their subsequent infusion, when we are convinced of readiness.
Since 2012, the main standard has always beenIt is maintained in an almost-ready-to-ship state (so even working drafts of the same high quality as the releases of the C ++ 98 and C ++ 11 standards). This has never happened before, when we kept the patient unsecured for a long time, with long lists of problems and organs spread around, which we are going to put back soon. Now we know that we can maintain a schedule with high quality work, because we always remain in a state of close readiness for release. If you would like, you could release a CD even now, without meeting in Cologne, and still the quality would be much higher than ever with a CD C ++ 98 or C ++ 11 (in truth, and their published standards) . And considering that C ++ 98 and C ++ 11 were successful, the understanding that now the quality is even higher means that we are on the right track.
C ++ 98 and C ++ 11 were developed for about 9 years and were very good products ...
Yes: 1989-1998 and 2002-2011.
... and C ++ 14 and C ++ 17 were minor releases. Is C ++ 20 a major release?
I repeat, I believe that it is correct to compare C ++ 14 + 17 + 20 as a whole: this is our nine-year cycle, but since we adhered to approach (2), we also released those developments that were ready to complete the three-year and six-year cycles .
Approach (2) allows you to achieve feature-based goals like P0592 for the next C ++?
Of course! While there are no words in it like “should include these features”, because then it will be the approach (1).
To strive for a certain set of features and give one of them priority is normal, but then it is a matter of priority. So far, we will only take what is ready, but we can choose what to work on first of all in order to prepare as soon as possible.