In C++17 there is couple changes to behavior of things which were already in C++.
1 ) auto x{ 1 } – now it’s int value, not initializer_list.
For a braced-init-list with only a single element, auto
deduction will deduce from that entry;
For a braced-init-list with more than one element, auto
deduction will be ill-formed.
For example:
1 2 3 4 5 |
auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int> auto x2 = { 1, 2.0 }; // error: cannot deduce element type auto x3{ 1, 2 }; // error: not a single element auto x4 = { 3 }; // decltype(x4) is std::initializer_list<int> auto x5{ 3 }; // decltype(x5) is int |
Standard paper related to this changes: n3922.
2) static_assert without message
Before it was possible create static_assert only with message like:
1 |
static_assert(std::is_abstract_v<T>, "T is not abstract"); |
and now message is optional parameter.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#include <iostream> #include <type_traits> template<class T> class A { static_assert(std::is_polymorphic_v<T>); }; class B { public: virtual void qwe() {} }; int main() { A<B> a; return 0; } |
3) Changed Technical Specification for range-loop
The existing range-based for
loop is over-constrained. The end iterator is never incremented,
decremented, or dereferenced. Requiring it to be an iterator serves no practical purpose.
C++11:
1 2 3 4 5 6 7 8 9 10 |
{ auto && __range = for-range-initializer; for ( auto __begin = begin-expr, __end = end-expr; __begin != __end; ++__begin ) { for-range-declaration = *__begin; statement } } |
C++17:
1 2 3 4 5 6 7 8 9 |
{ auto && __range = for-range-initializer; auto __begin = begin-expr; auto __end = end-expr; for ( ; __begin != __end; ++__begin ) { for-range-declaration = *__begin; statement } } |
Now begin() and end() can have different types, and it allows to write code like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
#include <iostream> struct FirstWord { std::string data; struct TheEnd { bool operator()(std::string::iterator i) { return *i != '\0' && *i != ' '; } }; std::string::iterator begin() { return data.begin(); } TheEnd end() { return TheEnd(); } }; bool operator!=(std::string::iterator i, FirstWord::TheEnd f) { return f(i); } int main() { for (auto c : FirstWord{ "ahah haha" }) { std::cout << c; } // output: ahah std::cout << std::endl; return 0; } |
Logic from range-loop can be moved to structure or class.
Standard paper related to this changes: p0184.