1 Introduction
C++17 introduces a new version of if/switch statement form, if (init; condition) and switch (init; condition), which can declare variables and initialize them directly in if and switch statements.
In the case of if, before C++17, we might write as follows:
{
auto val = GetValue();
if(condition(val))
{
// some codes if is true
}
else
{
// some codes if is false
}
}
It can be seen that val is in a separate scope, which exposes val to effects other than lf. In C++17, you can write as follows:
if(auto val = getValue(); condition(val))
{
// some codes if is true
}
else
{
// some codes if is false
}
In this way, val is only visible in if and else and will not leak into other scopes.
Note: val, a variable declared and initialized in if, is also valid in else.
2 init-state tasting
Here are just a few small attempts at this new feature, some tricks.
Case 1: Addressing Naming Difficulties
This part mainly uses the C++ 17init-state feature to reduce the naming of new variables, and mainly takes advantage of the fact that variables declared in if/else and switch have smaller scopes.
Assuming that a substring is found in a string, we can write as follows:
#include <iostream>
#include <string>
using namespace std;
int main()
{
const string myString = "My hello world string";
const auto it = myString.find("hello");
if(it != string::npos)
{
cout << it << " - Hello\n";
}
// you have to make another name different from it.
const auto it2 = myString.find("world");
if(it2 != string::npos)
{
cout << it2 << " - World\n";
}
return 0;
}
We can declare and define a new variable it2, or use it for a separate scope as follows:
{
const auto it = myString.find("hello");
if(it != string::npos)
{
cout << it << " - Hello\n";
}
}
{
const auto it = myString.find("world");
if(it != string::npos)
{
cout << it << " - World\n";
}
}
But in C++17, the new if-state syntax makes such scopes more concise:
if(const auto it = myString.find("hello"); it != string::npos)
cout << it << " - Hello\n";
if(const auto it = myString.find("world"); it != string::npos)
cout << it << " - World\n";
As mentioned earlier, variables in the if statement are still visible in else:
if(const auto it = myString.find("hello"); it != string::npos)
cout << it << " - Hello\n";
else
cout << it << " not found\n";
Case 2: if-initializer+structured binding
In addition, structured bindings can also be used in the new if-state grammar:
// better together: structured bindings + if initializer
if (auto [iter, succeeded] = mymap.insert(value); succeeded) {
use(iter); // ok
// ...
} // iter and succeeded are destroyed here
Here is a complete example:
#include <iostream>
#include <string>
#include <set>
using namespace std;
using mySet = set<pair<string,int>>;
int main()
{
mySet set1;
pair<string,int> itemsToAdd[3]{{"hello",1},{"world",1},{"world",2}};
for(auto &p : itemsToAdd)
{
// if-initializer + structured binding
if(const auto [iter,inserted] = set1.insert(p);inserted)
{
cout << "Value(" << iter->first << ", " << iter->second << ") was inserted\n";
}
else
{
cout << "Value(" << iter->first << ", " << iter->second << ") was not inserted\n";
}
}
return 0;
}