Recently, in the Finnish city of Oulu, the meeting of the
WG21 international working group on C ++ standardization ended, in which
Yandex employees officially participated for the first time. It approved a
draft version of C ++ 17 with a variety of new classes, methods and useful innovations of the language.

During the trip, we dined with
Bjarne Stroustrup , rode in the elevator with the
Coat of Arms Sutter , shook hands with
Behman Daves , went out for air
and breathed with
Vincent Bothe , discussed online games with
Gor Nishanov , were at the reception at the Oulu city hall and talked to the mayor. We also, together with everyone from 8:30 to 17:30, worked on the new C ++ standard, often gathering at 20:00 to work four more hours and have time to add a couple of good things.
')
Now we are ready to share with you the "goodies" of the new standard. Anyone wishing to have a look at the multi-threaded algorithms, new containers, unusual capabilities of old containers, “syntactic sugar” of the new wonderful C ++, please under the cat.
if constexpr ( condition )
In C ++ 17, it was possible to perform if at the compilation stage:
template <std::size_t I, class F, class S>
auto rget(const std::pair<F, S>& p) {
if constexpr (I == 0) {
return p.second;
} else {
return p.first;
}
}
. , :
- rget<0>( std::pair<char*, short>{} ) short;
- rget<1>( std::pair<char*, short>{} ) char*.
T& container::emplace_back(Args&&...)
emplace_back(Args&&...) sequence :
// C++11
some_vector.emplace_back();
some_vector.back().do_something();
// C++17
some_vector.emplace_back().do_something();
std::variant<T...>
: std::variant<T...> — union, .
std::variant<int, std::string> v;
v = "Hello word";
assert(std::get<std::string>(v) == "Hello word");
v = 17 * 42;
assert(std::get<0>(v) == 17 * 42);
boost::variant, :
- std::variant ;
- std::variant constexpr, constexpr ;
- std::variant emplace;
- — ;
- std::variant boost::static_visitor;
- std::variant ( `boost::make_recursive_variant<int, std::vector< boost::recursive_variant_ >>::type` ).
, ExecutionPolicy. , , :
std::vector<int> v;
v.reserve(100500 * 1024);
some_function_that_fills_vector(v);
//
std::sort(std::execution::par, v.begin(), v.end());
: , ExecutionPolicy, , std::terminate():
std::sort(std::execution::par, v.begin(), v.end(), [](auto left, auto right) {
if (left==right)
throw std::logic_error("Equal values are not expected"); // std::terminate()
return left < right;
});
. push pop():
// C++11
void push(std::multiset<value_type>&& items) {
std::unique_lock<std::mutex> lock(values_mutex_);
for (auto&& val : items) {
// ,
values_.insert(val);
}
cond_.notify_one();
}
value_type pop() {
std::unique_lock<std::mutex> lock(values_mutex_);
while (values_.empty()) {
cond_.wait(lock);
}
// ,
value_type ret = *values_.begin();
//
values_.erase(values_.begin());
return ret;
}
| // C++17
void push(std::multiset<value_type>&& items) {
std::unique_lock<std::mutex> lock(values_mutex_);
// , .
// (. #2)
values_.merge(std::move(items));
cond_.notify_one();
}
value_type pop() {
std::unique_lock<std::mutex> lock(values_mutex_);
while (values_.empty()) {
cond_.wait(lock);
}
// (. #2)
auto node = values_.extract(values_.begin());
lock.unlock();
// multiset'
return std::move(node.value());
}
|
C++17 , . pop() :
// rbtree '' (tree-node)
auto node = values_.extract(values_.begin());
// values_ , node
// values_mutex_ values_.
// , .
lock.unlock();
// , . std::move .
return std::move(node.value());
//
C++17 :
C++17 . , , , :
| |
---|
std::pair<int, double> p(17, 42.0);
| std::pair p(17, 42.0);
|
std::lock_guard<std::shared_timed_mutex> lck(mut_);
| std::lock_guard lck(mut_);
|
std::lock_guard<std::shared_timed_mutex> lck(mut_);
| auto lck = std::lock_guard(mut_);
|
std::string_view
C++17. C++11 , :
// C++11
#include <string>
void get_vendor_from_id(const std::string& id) { // , std::string
std::cout <<
id.substr(0, id.find_last_of(':')); //
}
// TODO: get_vendor_from_id(const char* id)
C++17 :
// C++17
#include <string_view>
void get_vendor_from_id(std::string_view id) { // , `const char*`, `char*`, `const std::string&` ..
std::cout <<
id.substr(0, id.find_last_of(':')); //
}
std::basic_string_view std::string_view — , , . Boost, boost::basic_string_ref boost::string_ref.
std::string_view C++17, std::string. <string_view> <string>, std::string_view .
:
- , string_view, , const std::string&, const char* ..;
- string_view ( `const string_view& id`, `string_view id`).
: string_view , , , '\0', string_view::data() , - .
if (init; condition)
:
// C++11
void foo() {
// ...
{
std::lock_guard<std::mutex> lock(m);
if (!container.empty()) {
// do something
}
}
// ...
}
, . C++17 :
// C++17
void foo() {
// ...
if (std::lock_guard lock(m); !container.empty()) {
// do something
}
// ...
}
lock if.
Structured bindings
std::set<int> s;
// ...
auto [it, ok] = s.insert(42);
// it — ; ok - bool .
if (!ok) {
throw std::logic_error("42 is already in set");
}
s.insert(it, 43);
// ...
Structured bindings std::pair std::tuple, :
struct my_struct { std::string s; int i; };
my_struct my_function();
// ...
auto [str, integer] = my_function();
...
C++17 :
- template <auto I> struct my_class{ /*… */ };
- filesystem — ;
- std::to_chars/std::from_chars — C ;
- std::has_unique_object_representations <T> — type_trait, «-» ;
- new alignment , ;
- inline — , ( inline );
- std::not_fn operator() const&, operator() && ..;
- . , , =, , — ;
- copy elision;
- ;
- std::string::data(), char* (!);
- constexpr , std::array ( :);
- std::iterator, std::is_literal_type, std::allocator<void>, std::get_temporary_buffer .. deprecated;
- , std::function;
- std::any — ;
- std::optional — , , , ;
- fallthrough, nodiscard, maybe_unused;
- constexpr ;
- [*this]( /*… */ ){ /*… */ };
- — type-erased , , ;
- lock_guard, ;
- .
C++Siberia ++ , , , , .