Toronto ISO C++ Committee Meeting Trip Report

Erich Keane erich.keane@verizon.net

C++ 17 Status

  • Was published as a "Draft International Standard" at the Kona meeting.
  • Ballots sent out to the "ISO National Bodies"
  • Ballot Voting closes in early September
    • If Unanimously accepted, automatically becomes the "International Standard" (no more Draft!)
    • Otherwise, a vote of the National Body Chairs will be held in November's New Mexico meeting.  If consensus is reached, becomes the "International Standard"

Evolution(EWG) Report:

  • Where I spent my whole time.
  • Tons of work!  Only including stuff that didn't make it through 'core'.
  • Not including things that were rejected, unless super interesting.

P0132R0: Non-throw container Ops:

  • Discussed approach for push_back/etc stuff to have no throw alternatives.  bool push-back(nowthrow_t, const T&); vs bol push_back_nowthrow(const T);
  • Referred to Library Evolution (LEWG) with encouragement.

P0702R0:

vector v{vector{1,2}};

  • What is the meaning of the above?  Is this an initializer-list or a move/copy call?
  • Encouraged "copy/move" instead of init list.
tuple t {tuple {1,2}}; // decltype(t) is tuple<int,int> as of Kona
// decltype(v) was unclear.  Previously could be vector<vector<int>>
// Directions to Core WG to make a Defect against 17 and be vector<int>
vector v{vector{1,2}}; 

P0654R0:explict structs

  • A struct that requires all fields to be initialized.
  • Decided against.
explicit struct E {
 Color c;
 int r;
};

E e; // error, doesn't init everything.
E e1{Color::red}; // Same.

P0627R1:Unreachable

  • Standardize "unreachable"
//Suggested as an attribute, similar to fallthrough:
void f() {
switch (something) {
default:
[[unreachable]]; // note needs semicolon.
case 1:
 //...
}
}

// Guidance to change to a function:
void f() {
switch (something) {
default:
std::unreachable("abc"); // string optional.
case 1:
 //...
}
}

Modules + Concepts

  • Massive discussions.
  • Minor changes to Modules suggested.
  • Concepts lost 'bool' keyword in definition.
  • Semantic constraint matching changed (when are 2 concepts related?).
  • Concepts had 'terse' syntax removed.
    • Further work on terse syntax strongly supported.

P0238R1: Terser Lambdas?

  • Proposed some changes to lambdas, altering the syntax.
  • Guidance to follow up, but no real decisions.
[](auto const& s) => s == 2;
// Equivalent to:
[](auto const& s) noexcept(s == 2) -> decltype((s==2)) {
 return s == 2;
}

P0624R0: Default ctor stateless Lambdas:

  • Lambdas cannot be put into a map due to lack of a default ctor.  Also not copy-able.
  • Guidance to enable default ctor, copies for stateless.
auto greater = [](auto a, auto b) {return a > b;};
std::map<std::string, int, decltype(greater) map; // illegal :(

decltype g;
g = greater; // meaningless, but illegal.

P0634R0: Down with typename

  • Relax need for 'typename' when the compiler 'knows'.
// why typename necessary? only a type is legal.
template<class T> struct D : typename T::B {};
static_cast<typename T::B>(...);
template<typename T>
void foo(T t) -> typename T::B {...};
// This:
template<class T> typename T::R f(typename T::P);
template<class T> struct S {
  using Ptr = typename PtrTraits<T>::Ptr;
  typename T::R f(typename T::P p) {
    return static_cast<typename T::R>(P);
  }
  auto g() -> typename S<T*>::Ptr;
};

//Becomes:
template<class T> T::R f(T::P);
template<class T> struct S {
  using Ptr = PtrTraits<T>::Ptr;
  T::R f(T::P p) {
    return static_cast<T::R>(p);
  }
  auto g() -> S<T*>::Ptr;
};

P0619R1: Review Deprecated Things

  • 3 Items in Annex D for EWG to look into:
// Exception specifiers:
void foo() throw() {} // throw() deprecated
// Guidance to delete.

// Redecl of static constexpr data members:
struct A {
  static constexpr int n = 5;
};
constexpr int A::n; // deprecated, stays that way.

// Implicit copy assign/construct.
// copy/assign/dtor definition don't delete eachother:
struct S {
  S(const S&); // copy assignment still implicit
  S(S&&);// move assignment deleted.
};

P0614R0: range-for init

  • Add C++17 while/if initializer to range-fors.
// Fixes 'dangling r-value' issue here:
for (T thing = f(); auto& x : thing.times()) {}

// Allows this:
for (size_t i = 0; const auto& x : foo()){
++i;
//...
}
// To Core in NM.

P0572R1: bit_sizeof/bit_offsetof

  • Guidance to add these two as operator-like functions.
struct S {
 unsigned A : 5;
 unsigned B : 4;
 unsigned C : 3;
};

//bit_sizeof(S::B) == 4
//bit_offsetof(S, C) == 9

P0639R0: constexpr_containers?

  • Existing proposals for constexpr_vector
  • Should we abandon this, and see if we can make existing containers things legal to be constexpr?
  • Guidance to 'work more on it':
    • Make a constexpr-new/delete version.
    • Make placement-new constexpr in certain situations
    • Alter std::allocator to use these new features.

P0665R0: Class template specialization out of NS:

  • Currently, class template specializations need to happen in the original namespace.  Lets relax that:
// guidance to encourage further work:
namespace my {
struct tuple_like { /* ... */ };
template <>
struct ::std::hash<tuple_like> { /* ... */ };
template <>
struct ::std::tuple_size<tuple_like> { /* ... */ };
template <>
struct ::std::tuple_element<tuple_like> { /* ... */ };
/* ...other declarations in my namespace... */
}

SG7 (Reflection) Report:

  • Extensive discussion on Static reflection of Functions
  • A bunch of stuff already exists.
  • Discussion of 'metaclasses', encouraged work, but not approach.

Final Votes From Plenary

  • Many now go into the "Working Draft" for C++2a.
  • Comments/papers are still welcome to fix/improve.
  • Many have more improvements in the pipeline.
  • "TS" : Technical Specification
  • "PDTS" : Preliminary Draft for TS

P0683R1: Bit-field default init:

  • Was previously left out due to complexity/parse issues.
int a;
struct S {
  int x : 8 = 42; // Allow this!
  int y : true ? 8 : a = 42; // This and the below are troublesome
  int z : 1 || new int {0};
};
// Solution is to 'Max Munch'
// From Standard:
 int a;
  const int b = 0;
  struct S {
    int x1 : 8 = 42;               // OK; "= 42" is brace-or-equal-initializer
    int x2 : 8 { 42 };             // OK; "{ 42 }" is brace-or-equal-initializer
    int y1 : true ? 8 : a = 42;    // OK; brace-or-equal-initializer is absent
    int y2 : true ? 8 : b = 42;    // error: cannot assign to const int
    int y3 : (true ? 8 : b) = 42;  // OK; "= 42" is brace-or-equal-initializer
    int z : 1 || new int { 0 };    // OK; brace-or-equal-initializer is absent
  };

P0409R2: [=, this] capture

  • Clarify capture rules in the case of default-copy in lambdas.


void Type::foo() {
[=] () {}; // captures 'this' by pointer
[=, *this] () {}; // captures 'this' by copy.
[=,this]() {} // same as 1st, but now explicit.
}

P0329R4: Designated Inits

  • C has named initializers, lets get them too (sorta).
struct A { int x; int y; int z; };
A a{ .x = 1, .z = 2}; // Now legal!

// Limitations over C: 
// Must match declaration order (preserves unwrap order)
// No array initializers (conflicts with lambda syntax)
struct A { int x, y; };
struct B { struct A a; };
struct A a = {.y = 1, .x = 2};  // valid C, invalid C++
int arr[3] = {[1] = 5};        // valid C, invalid C++
struct B b = {.a.x = 0};       // valid C, invalid C++
struct A a = {.x = 1, 2};      // valid C, invalid C++

P0428R2: Templating Lambdas!

  • Allow SFINAE/enable_if, plus good for Concepts.
// Syntax: Add '<..>' for template, no template keyword:
//[capture-list]<template-list>(param-list){stmt-list}

auto ident = [=]<typename T>(T& t) { return t; };

P0428R2: Templating Lambdas!

  • Allow SFINAE/enable_if, plus good for Concepts.
// Syntax: Add '<..>' for template, no template keyword:
//[capture-list]<template-list>(param-list){stmt-list}

auto ident = [=]<typename T>(T& t) { return t; };

P0734R0: Concepts->WD

  • Concepts are now in C++2a!  Syntax altered during the meeting.
// 'bool' removed from definition:
template<typename T>
concept EqualityComparable = requires(T a, T b) { 
{a ==b }->bool; 
};


// 'terse' syntax killed.
void f(EqualityComparable e); // Not legal

template<EqualityComparable T>
void f (T e); // Still allowed

template<typename T> requires EqualityComparable<T>
void f( T e); // Alternate definition syntax.

P0463R1: endian, Just endian

  • Ability to tell endianness (library):
// type_traits header:

enum class endian
{
    little = ...,
    big    = ...,
    native = ...
};

P0674R1: array make_shared

  • Let make_shared/allocate_shared work with Arrays:
// 23.11.2.2.6, shared_ptr creation
template<class T, class... Args>
  shared_ptr<T> make_shared(Args&&... args); // T is not array
template<class T, class A, class... Args>
  shared_ptr<T> allocate_shared(const A& a, Args&&... args); // T is not array

template<class T> shared_ptr<T> make_shared(size_t N); // T is U[]
template<class T, class A>
  shared_ptr<T> allocate_shared(const A& a, size_t N); // T is U[]

template<class T> shared_ptr<T> make_shared(); // T is U[N]
template<class T, class A>
  shared_ptr<T> allocate_shared(const A& a); // T is U[N]

template<class T>
  shared_ptr<T> make_shared(size_t N, const remove_extent_t<T>& u); // T is U[]
template<class T, class A>
  shared_ptr<T> allocate_shared(const A& a, size_t N,
    const remove_extent_t<T>& u); // T is U[]

template<class T> shared_ptr<T>
  make_shared(const remove_extent_t<T>& u); // T is U[N]
template<class T, class A>
  shared_ptr<T> allocate_shared(const A& a,
    const remove_extent_t<T>& u); // T is U[N]

Others:

  • Modules TS approved (To PDTS).
  • A few Coroutines TS changes.
  • A bunch of Ranges TS fixes.
  • A bunch of Networking TS fixes.
  • 1 Parallelism TS V2 fix.
  •  

Fin

 

N4681: Modules -> PDTS!

  • Modules TS approved!

deck

By Erich Keane

deck

  • 716