C/C++ and Fortran

 View Only

The view from C++ Standard meeting April 2013 Part 1

By Archive User posted Thu April 25, 2013 02:25 PM

  

Originally posted by: Michael_Wong


Bristol is a terrific place. It is where much of the history of steam and iron occurred to change the world, although at the time people probably did not realize it. Isambard Kingdom Brunel had in the 19th century, revolutionized the way we travel, by bringing together steam engine to replace the paddlewheel along with iron to create an ocean going vessel that lasted far longer than any vessel at the time, the SS Great Britain. Just as it had a great many detractors who said it couldn’t be done, many people said a new Standard could not be created so quickly just after C++11. Well, The C++ Standard Committee is well on its way to changing the minds of those detractors.

This is because Bristol is also where the C++ Std will change the world in many ways. At this meeting, updates are being added to C++14 which will effectively be a new language standard on top of C++11. A new Committee Draft (CD) will be issued based on the cumulative work up to this meeting and it will be out for review. Our goal was to triage all features that can enter C++14. This means C++14 is more than just bug fixes and is unlike a Technical Corrigendum like TC1 which bridged C++ 1998 to C++2003. As such it will have additional features beyond defect fixes that has been deemed to be small enough in scope and solution but significant enough in annoyance that it should be fixed immediately post C++11.

To get an overview of the papers, please see the 4 blog (Part 1, 2, 3, 4) series by Jens from Meeting C++.

This may surprise a few but as already pointed out in my Portland C++ Std Trip report, it is the intention to issue a quick bug fix release, while addressing some of the minor features for C++14.

The tension it adds to this week’s workload was evident as many working groups had to prioritize likely C++14 items first, before C++17 items. The added tension is evident in the Mock Plenary session Friday afternoon which became officially the longest in my memory. It started at 1:30 pm and ended at 6:45 pm, exceeding the plenary session from the Fermi Lab meeting by almost half an hour.

Let me say what a Mock Plenary is. The afternoon before the real vote, we get together to run through a simulation of the vote to expose all the positions, and especially the controversies. This gives enough time to hash out the controversies without the time pressure of people having to catch flights. It also allows controversies to be fixed by the real vote or removed.

So this one, by my measure was both long and controversial. It definitely has its share of passionate fireworks. It was long because both Core and Library had a large number of motions, if not the most I have seen recently. As such, I will have to break up this trip report into several parts: Language, Library, Concurrency, and Transactional Memory. This is part of trying to catch the bus before it leaves as C++14 will go to CD ballot. After that, there is still a small chance to add something in the next C++ Standard meeting, but it will require a National Body comment on the CD ballot, or a serious defect. But after the Chicago meeting, this will likely go to a DIS (Draft International Standard) which takes a 5 month ballot and then a 2 month ballot to get to a Final Draft International Standard. Working backwards, this will put us in mid 2014 with some buffer zone, in case things goes wrong.

http://isocpp.org/std/iso-iec-jtc1-procedures

This means it actually prevented a large number of defect fixes to be processed because every chair was tasked with C++14 work before their normal load. I cannot reiterate all the votes as there will be an official paper in the post-meeting mailing.

By contrast the Saturday afternoon vote is almost quiet as we go through with any objection to unanimous consent on each motion. As such I will first comment on what I think are the more interesting  features, some of which Herb has already blogged about. Many of these may have little or no controversy.

I will also comment on some of the more controversial ones covering those that were removed based on Friday’s Mock Vote and the remaining ones that did not have unanimous consent. Note that I am not the secretary and any actual vote results should be verified with the minutes, but I don’t think I am far off.

I also comment on the defeated or withdrawn proposals that resulted from the controversy in the Mock Plenary. In some of these cases, the proposal might still return because there is still time to add these proposal back if there is a National Body comment from the CD ballot.

Here are the new language extensions voted in and I will use the paper link number instead of feature description. Normally I would not, but since Jens blog has been using those links, and many people can access the Standard paper website, the paper number are generally well known anyway. But in many cases, the paper numbers approved are the core or library language paper developed at the meeting so is unknown on the website until the post-meeting mailing appears. These papers have no hot link as they are inaccessible to the public until the post-meeting mailing. In these cases, I will trace back to the website papers that motivated the wording change. I will also skip a few papers that are really minor language defect fixes.

  • N3472 (post-Portland) where Binary  Literals is now accepted as core syntax using 0b/0B prefix as you would want. It is also in existing GCC/Clang extensions and is the same syntax in Java7, Python, and D. It looks like 0b10001111.
  • N3639, a continuation of N3497 runtime sized array as a language feature accepted. This is a consistent form of VLA for C++ using a runtime bound for an array. This is not C99 VLA which in some opinion is an abomination. This is VLA as it should have been. But because there were concerns that some part of N3638 may conflate with the library dynarray feature, it lead to this vote to become slightly controversial. Once it was clarified that the library issue does not depend on this, and that it is independent, this vote sailed through relatively unscathed.
  • N3638, a continuation of N3582:  since we allowed lambdas to have return type deduction under special cases (such as whenever there is only a single actual executable statement), it seems to make sense that this be gifted back to normal functions. This is one of those symmetrical alignment that was missed during C++11 that becomes obvious afterwards. Now it is in C++14.
  • N3648  is really the wording developed from N3610 which will give us essentially move capture in lambdas. This is important for moving say, a unique_ptr into the lambda and defining new local variables in the lambda. This is in fact implemented by Jakko Jarvi from his original proposal for lambda.
  • N3653 is the core wording for N3605 and is another patch to increase symmetry. Aggregate types came into C++ as a C compatiblilty feature and had not changed much. Bjarne Stroustrup pointed out that aggregate initialization can't be used if a class has member-initializers. He provided the following example:

 

struct Univ {

    string name;

    int rank;

    string city = "unknown";

};

 

void t1()

{

    Univ u = {"Columbia",10};

    cout << u.name << ' ' << u.rank << ' ' << u.city << '\n';

}

 

 There is no reason why they can’t. So the rules were relaxed to allow member initialization in aggregate classes, using the same rules as in C++11.

  • N3667 is a core issue 1402 fix where we found implicitly defined move functions were too often deleted by our rules. This relaxes the rules.
  • N3652 describes the subset of N3597 selected for inclusion in C++14, relaxing a number of restrictions on constexpr functions. These changes all received overwhelmingly strong or unopposed support under review of the Evolution Working Group. It also incorporates Option 2 of N3598.about relaxing constraints on constexpr. This second part had a great deal of controversy. The first part is non-controversial:
    1. Allow declarations within constexpr functions, other than:
      1. static or thread_local variables
      2. uninitialized variables
    2. Allow if and switch statements (but not goto)
    3. Allow all looping statements: for (including range-based for), while, and do-while
    4. Allow mutation of objects whose lifetime began within the constant expression evaluation.

The second part is the removal of the implicit constness of constexpr non-static member function. This implicit constness creates problems for literal class types which desire to be usable both within constant expressions and outside them. This is about allowing more elaborate computations and making them implicitly const prevents mutation of data. This was controversial as some feel this is not really attacking the underlying problem. We can't bind a temporary to a non-const reference but one can call a non const member function on a temporary of class type. There is some ABI concerns with variable mutation and there is some chance this will require code change but the longer we wait for this fix, the more code there will be in the field. We also could have chosen to leave the issue and let the user deal with it with a const_cast, or add a qualifier like mutable to enable removal of the implicit constness. All these were mildly rejected, though not by much.

  • N3499 is about supporting digit separators and it is the prototypical bikeshed (meaning everyone have their personal favorite). THIS WAS NOT PASSED. The solution uses .. as a way to resolve ambiguity but in most cases will use a single underscore. C compatibility is possible with this solution. So if you have a suffix that can cause conflict, such as 100 with a 3d coordinate, then 100_3d is not possible and must be replaced with 100..3d. This was extremely controversial. We have looked at many alternatives and they are nicely listed in N3499  and all of them conflict in some way with some other language, or some tool, or parsing system. This solution was deemed to be the best we can get. But it is not intuitively satisfying as it is somewhat incomplete. But then the Standard is never about getting the best solution, the enemy of the good. The controversy arose because there is a large segment who prefer to have no solution at all, if we can’t have the best solution. Most of those who opposed do not have a solution either that can solve all the corner cases. In reality, digit separators is useful really only for writing very large numbers. I would argue this is a corner case where you are writing binary, octal, or very large decimals. Even time notations are better written as multiplication of seconds and minutes instead of the final product to make it clear where the value comes from without loss of efficiency because in many cases compiler would fold the result into a constant. My personal feeling? This is not a problem worth solving when we have spent more than a day with 20 experts’ time in total since 3 meetings ago. If the solution is obvious and simple, then it would be worth the time. There are far more interesting and useful problem to solve. You may feel differently.
  • N3664 is based on N3537 and is a small optimization where today we have one call for each allocation for each new and delete. Now optimizers are allowed to batch them. This is similar to copy elision already being permitted today.
  • N3651 is based on N3615 and  is a proposal to support constexpr template variables.  This replaces the use of static data members for parameterized constants, because these have annoyances of requiring duplicate declarations: once inside the class template, once outside the class template to provide the “real” definition in case the constants is odr-used. Herb provided one example from the paper. Here is another also from the paper using definitions of fundamental Pauli matrices (used in quantum mechanics):

 

struct matrix_constants {

   template<typename T>

      using pauli = hermitian_matrix<T, 2>;

   template<typename T>

      constexpr pauli<T> sigma1 = { { 0, 1 }, { 1, 0 } };

   template<typename T>

      constexpr pauli<T> sigma2 = { { 0, -1i }, { 1i, 0 } };

   template<typename T>

      constexpr pauli<T> sigma3 = { { 1, 0 }, { -1, 0 } };

};

  • N3649 is about generic lambdas and is based on N3559. This will replace the need to name the specific type of lambda parameter types by naming them as auto. It is probably one of the most requested feature after C++11. Some opposed this because there is concern that it should be delayed until we have a Concepts TS when constrained lambdas would also need to be specified. This example has been discussed extensively by Herb. Under the cover, a polymorphic lambda can essentially be modeled with a templated anonymous functor that looks likes this so it should be easily implementable.

[] ( auto p1, const auto& p2 ){f( p1, p2 ); }

// implemented as:

class __functor {

public:
  template<typename T1, typename T2>
  void operator()( T1 p1, const T2& p2 ) {

      f(p1, p2 );

   }

};

 

C++14 will also have the changes we made in Portland:

  • N3323, is a  Proposal to Tweak Certain C++ Contextual Conversions in four distinct cases and cleans up the use cases.

as well as  many defect fixes numbering into one hundred. I will stop here and post in the next report on Library features, Technical Specification, Concurrency features, and Transactional Memory.

0 comments
1 view

Permalink