Полезные новации С++17. Инициализирующее выражение для if/switch.
Новая версия выражений if и switch для С++:
Ранее мы должны были писать так:
{ auto val = GetValue(); if (condition(val)) // on success else // on false... }
Фигурные скобки введены сознательно, дабы ограничить область видимости val и предотвратить его "утечку" в окружающее выражение.
Теперь мы можем написать:
if (auto val = GetValue(); condition(val)) // on success else // on false...
val теперь видимо только внутри if и else выражений ("утечка" исключена). condition может быть любым условием - не только для случая, когда val имеет булево значение.
Почему это полезно?
Допустим мы хотим найти что-то в строке:
const std::string myString = "My Hello World Wow"; const auto it = myString.find("Hello"); if (it != std::string::npos) std::cout << it << " Hello\n" const auto it2 = myString.find("World"); if (it2 != std::string::npos) std::cout << it2 << " World\n"
Мы должны использовать различные имена для итераторов, либо замкнуть их в разные области видимости:
{ const auto it = myString.find("Hello"); if (it != std::string::npos) std::cout << it << " Hello\n" } { const auto it = myString.find("World"); if (it != std::string::npos) std::cout << it << " World\n" }
Новое выражение if создаёт дополнительную область видимости одной строкой:
if (const auto it = myString.find("Hello"); it != std::string::npos) std::cout << it << " Hello\n"; if (const auto it = myString.find("World"); it != std::string::npos) std::cout << it << " World\n";
Как упоминалось выше, переменная , определённая в выражении if также видима в блоке else. Таким образом, можно написать:
if (const auto it = myString.find("World"); it != std::string::npos) std::cout << it << " World\n"; else std::cout << it << " not found!!\n";
Итак - работающий пример:
#include <iostream>
#include <string>
int main()
{
const std::string myString = "Hello World";
auto it = myString.find("Hello");
if (it != std::string::npos)
std::cout << it << " Hello\n";
auto it2 = myString.find("World");
if (it2 != std::string::npos)
std::cout << it2 << " World\n";
// additional enclosing scope so 'it' doesn't 'leak'
{
auto it = myString.find("Hello");
if (it != std::string::npos)
std::cout << "Hello\n";
}
{
auto it = myString.find("World");
if (it != std::string::npos)
std::cout << "World\n";
}
// C++17 with init if:
if (const auto it = myString.find("Hello"); it != std::string::npos)
std::cout << it << " Hello\n";
if (const auto it = myString.find("World"); it != std::string::npos)
std::cout << it << " World\n";
}
Особенно мне понравилась возможность использования этого вместе со структурированным связыванием (что такое 'structured binding' надо будет рассказать отдельно):
// better together: structured bindings + if initializer if (auto [iter, succeeded] = mymap.insert(value); succeeded) { use(iter); // ok // ... } // iter and succeeded are destroyed here
Ещё рабочий пример:
#include <iostream>
#include <set>
#include <string>
#include <tuple>
#include <utility>
using namespace std;
int main()
{
set<pair<string, int>> mySet;
pair<string, int> itemsToAdd[3] { {"hello", 1}, { "world", 2 }, { "world", 2 } };
for (auto &p : itemsToAdd)
{
if (const auto [iter, inserted] = mySet.insert(p); inserted)
cout << "Value(" << iter->first << ", " << iter->second << ") was inserted" << "\n";
else
cout << "Value(" << iter->first << ", ...) not inserted!" << "\n";
}
}
Поддержка:
GCC: 7.0, Clang: 3.9, MSVC: in VS 2017.3.
Подробности:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r1.html
https://www.youtube.com/watch?v=AiXU5EuLZgc&feature=youtu.be
https://herbsutter.com/2016/06/30/trip-report-summer-iso-c-standards-meeting-oulu/
if (init; condition) и switch (init; condition).Ранее мы должны были писать так:
{ auto val = GetValue(); if (condition(val)) // on success else // on false... }
Фигурные скобки введены сознательно, дабы ограничить область видимости val и предотвратить его "утечку" в окружающее выражение.
Теперь мы можем написать:
if (auto val = GetValue(); condition(val)) // on success else // on false...
val теперь видимо только внутри if и else выражений ("утечка" исключена). condition может быть любым условием - не только для случая, когда val имеет булево значение.
Почему это полезно?
Допустим мы хотим найти что-то в строке:
const std::string myString = "My Hello World Wow"; const auto it = myString.find("Hello"); if (it != std::string::npos) std::cout << it << " Hello\n" const auto it2 = myString.find("World"); if (it2 != std::string::npos) std::cout << it2 << " World\n"
Мы должны использовать различные имена для итераторов, либо замкнуть их в разные области видимости:
{ const auto it = myString.find("Hello"); if (it != std::string::npos) std::cout << it << " Hello\n" } { const auto it = myString.find("World"); if (it != std::string::npos) std::cout << it << " World\n" }
Новое выражение if создаёт дополнительную область видимости одной строкой:
if (const auto it = myString.find("Hello"); it != std::string::npos) std::cout << it << " Hello\n"; if (const auto it = myString.find("World"); it != std::string::npos) std::cout << it << " World\n";
Как упоминалось выше, переменная , определённая в выражении if также видима в блоке else. Таким образом, можно написать:
if (const auto it = myString.find("World"); it != std::string::npos) std::cout << it << " World\n"; else std::cout << it << " not found!!\n";
Итак - работающий пример:
#include <iostream>
#include <string>
int main()
{
const std::string myString = "Hello World";
auto it = myString.find("Hello");
if (it != std::string::npos)
std::cout << it << " Hello\n";
auto it2 = myString.find("World");
if (it2 != std::string::npos)
std::cout << it2 << " World\n";
// additional enclosing scope so 'it' doesn't 'leak'
{
auto it = myString.find("Hello");
if (it != std::string::npos)
std::cout << "Hello\n";
}
{
auto it = myString.find("World");
if (it != std::string::npos)
std::cout << "World\n";
}
// C++17 with init if:
if (const auto it = myString.find("Hello"); it != std::string::npos)
std::cout << it << " Hello\n";
if (const auto it = myString.find("World"); it != std::string::npos)
std::cout << it << " World\n";
}
Особенно мне понравилась возможность использования этого вместе со структурированным связыванием (что такое 'structured binding' надо будет рассказать отдельно):
// better together: structured bindings + if initializer if (auto [iter, succeeded] = mymap.insert(value); succeeded) { use(iter); // ok // ... } // iter and succeeded are destroyed here
Ещё рабочий пример:
#include <iostream>
#include <set>
#include <string>
#include <tuple>
#include <utility>
using namespace std;
int main()
{
set<pair<string, int>> mySet;
pair<string, int> itemsToAdd[3] { {"hello", 1}, { "world", 2 }, { "world", 2 } };
for (auto &p : itemsToAdd)
{
if (const auto [iter, inserted] = mySet.insert(p); inserted)
cout << "Value(" << iter->first << ", " << iter->second << ") was inserted" << "\n";
else
cout << "Value(" << iter->first << ", ...) not inserted!" << "\n";
}
}
Поддержка:
GCC: 7.0, Clang: 3.9, MSVC: in VS 2017.3.
Подробности:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r1.html
https://www.youtube.com/watch?v=AiXU5EuLZgc&feature=youtu.be
https://herbsutter.com/2016/06/30/trip-report-summer-iso-c-standards-meeting-oulu/
Комментарии
Отправить комментарий