7 Features of C++17 that will simplify your code

fenbf
32.4K views

Open Source Your Knowledge, Become a Contributor

Technology knowledge has to be shared and made accessible for free. Join the movement.

Create Content

Structured Bindings

Do you often work with tuples?

If not, then you probably should start looking at it. Not only are tuples suggested for returning multiple values from a function, but they've also got special language support - so that the code is even easier and cleaner.

For example (got it from std::tie at cppreference):

std::set<S> mySet;
 
S value{42, "Test", 3.14};
std::set<S>::iterator iter;
bool inserted;
 
// unpacks the return val of insert into iter and inserted
std::tie(iter, inserted) = mySet.insert(value);

if (inserted)
    std::cout << "Value was inserted\n";

Notice that you need to declare iter and inserted first. Then you can use std::tie to make the magic... Still, it's a bit of code.

With C++17:

std::set<S> mySet;
 
S value{42, "Test", 3.14};

auto [iter, inserted] = mySet.insert(value);

One line instead of three! It's also easier to read and safer, isn't it?

Here's the full working code:

std::tie example
1
2
3
4
5
6
7
8
9
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <cstdlib>
#include <iostream>
#include <set>
#include <string>
#include <iterator>
#include <tuple>
// {...}
int main()
{
std::set<S> mySet;
// pre C++17:
{
S value{42, "Test", 3.14};
std::set<S>::iterator iter;
bool inserted;
// unpacks the return val of insert into iter and inserted
std::tie(iter, inserted) = mySet.insert(value);
if (inserted)
std::cout << "Value was inserted\n";
}
// with C++17:
{
S value{100, "abc", 100.0};
const auto [iter, inserted] = mySet.insert(value);
if (inserted)
std::cout << "Value(" << iter->n << ", " << iter->s << ", ...) was inserted" << "\n";
}
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Also, you can now use const and write const auto [iter, inserted] and be const correct.

Structured Binding is not only limited to tuples, we have three cases:

1. If initializer is an array:

// works with arrays:
double myArray[3] = { 1.0, 2.0, 3.0 };  
auto [a, b, c] = myArray;

2. if initializer supports std::tuple_size<> and provides get<N>() function (the most common case I think):

auto [a, b] = myPair; // binds myPair.first/second

In other words, you can provide support for your classes, assuming you add get<N> interface implementation.

3. if initializer's type contains only non static, public members:

struct S { int x1 : 2; volatile double y1; };
S f();
const auto [ x, y ] = f();

Now it's also quite easy to get a reference to a tuple member:

auto& [ refA, refB, refC, refD ] = myTuple;

And one of the coolest usage (support to for loops!):

std::map myMap;    
for (const auto & [k,v] : myMap) 
{  
    // k - key
    // v - value
} 

Can you help me with the code below and make it working?

iteration over map, finish the code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <map>
#include <string>
#include <tuple>
int main()
{
const std::map<std::string, std::string> capitals {
{ "Poland", "Warsaw"},
{ "USA", "Washington"},
{ "France", "Paris"},
{ "UK", "London"},
{ "Germany", "Berlin"}
};
// can you write code that shows prints Country: Capital ?
// eg "Poland : Warsaw" ?
for...
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

BTW: Structured Bindings or Decomposition Declaration?

For this feature, you might have seen another name "decomposition declaration" in use. As I see this, those two names were considered, but now the standard (the draft) sticks with "Structured Bindings."

More Details in:

Working in GCC: 7.0, Clang: 4.0, MSVC: in VS 2017.3.

Open Source Your Knowledge: become a Contributor and help others learn. Create New Content