The 2016 summer C++ standards meeting is over. This meeting has the record to be (at least to my knowledge) the northest meeting we have ever had. According to several sources the distance from the venue to the Arctic circle was around 100 KM. It was really shocking to have no night at all. It did not matter what your clock said, the sun was almost always around.
So, what has happened here? Well the big headline is that we approved to issue the CD (committee draft) for C++17. Now we will have a period where national standards bodies will have the opportunity (and are expected) to issue comments on every page of the standard. Those comments will be processed in the next meeting to be held in November in Issaquah (Washington, USA).
So. If you have any comments, contact to your standards national body. In case you are Spanish, please contact me.
Now I will try to summarize the new additions that we approved for c++17. However do not expect that this post contains an exhaustive list. I leave that to others. My list is based on things I can easily state in post and that I consider interesting for most developers. Or things, that I am interested for some particular reason.
In this post you will find the language part. You will have to wait for the library part a few days more.
Here is my list:
- We now can use attribute namespaces without repeating the namespace in front of every attribute. For this we have a new prefix using in attributes.
[[using rpr: kernel, target(gpu), in(x), out(y,z)]] // Same as // [[rpr::kernel, rpr::target(gpu), rpr::in(x), rpr::out(y,z)]]
- A new form of operator new, takes and additional parameter of type std::align_val_t to be used with over-aligned data types.
- The rules for template argument deduction currently valid for functions have been extended so that now can be applied to constructors:
std::pair p{3.5, 2}; // p is pair<double,int> std::mutex m; auto l = std::lock_guard{m}; // l is lock_guard<std::mutex>
- Non-type template parameters can be declared with auto. This allows to write simpler templates:
// C++14 template <typename T, T v> struct S { /*...*/ }; S<decltype(x), x> s; // C++17 template <auto v> struct S { /*...*/ }; S<x> s;
- While there is a number of cases where copy elision is optional in C++, C++17 makes it mandatory for the case where a temporary object is used to initialize another object. This happens, for example, when a temporary is returned from a function.
- The order of evaluation of some expressions is now fixed. This solves problems with very idiomatic constructs whose order of evaluation is not fixed in C++14.
s.replace(0, 4, “”).replace(s.find(“even”), 4, “only”).replace( s.find(“ don’t”), 6, “”);
Note that not all orders are fixed. In particular it is still not fixed the order in which function arguments are evaluated.
- While the use of attributes and scoped attributes that are not defined in the standard is still implementation defined, the use of attributes that are not recognized by an implementation should be ignored. This allows that tools can define attributes in their own namespace without risk that a compiler issues errors because of that.
- A compile-time solution for if is provided through if-constexpr which allows that template code is instantiated depending on compile-time condition.
template<typename T, typename ... Rest> void g(T&& p, Rest&& ...rs) { if constexpr (sizeof...(rs) > 0) g(rs...); // never instantiated with an empty list. }
- The inline specifier can now be applied to variables. Those variables can be defined in multiple translation units (with exactly the same definition) and generate a single variable. Static data members which are constexpr are implicitly inline.
class X { constexpr static int max = 10; //... }; const int X::max; // No longer needed
This also allows to define global variables in header files without needing a definition in some translation unit.
// Header A.h inline int x=42; // Header B.h inline int x=42
- Structured bindings allow to get multiple values returned by a function in multiple variables.
tuple<int,string> f(); auto [x, y] = f(); // x->int, y->string struct A { int n; double x; char c; }; A g(); auto [x,y,z] = g();
- If and switch statements may now include an initialization before the condition that has the scope of that statement.
if (int x = get_value(); x>0) { use(x); } switch (auto z = get_enum(); z) { case val1: do_something(z); break; case val2: do_other(z); break; }