_, щоб зручно було користуватися зіставленням із взірцем (паттерн-матчінгом), якого звісно досі нема, або, наприклад, розпаковувати кортежі на кшталт:auto [x, y, _] = f();
Тут типу третє значення нам не суттєве, тож можна використати
_, щоб не вигадувати імʼя, а потім боротися з ворнінгами про те, що воно не використовується, додаючи [[maybe_unused]].Та C++ би не був собою, якби все було так прозоро. Ніщо не заважає вам і зараз використати
_ як імʼя змінної:auto [x, _] = make_pair(1, 2);
cout << x << "," << _ << endl; // використання
Тож це працюватиме й надалі. Однак інколи хочеться зробити так двічі в одному скоупі, а structured binding — це визначення нової змінної, а не просто запис у ту, що вже існує:
auto [x, _] = make_pair(1, 2);
auto [_, y] = make_pair(3, 4);
Зараз такий код генерує
error: conflicting declaration ‘auto _’, бо це повторна декларація змінної, а от з новим пропоузалом перестане. Тобто можна навіть вручну скільки завгодно разів оголошувати змінну
_, і жодних проблем… доти, доки не спробувати звернутися до змінної _ у цьому ж скоупі. Якщо вона оголошена один раз, то можна, а якщо декілька, то це помилка:auto _ = 42; // Оголошення
auto _ = 0; // Повторне оголошення
{
auto _ = 1; // Новий скоуп. Оголошення з шадовінгом
assert( _ == 1 ); // Можна прочитати
}
assert( _ == 42 ); // Не можна прочитати 🙂
В принципі, очевидно, еге ж?) А, до речі… У неймспейсі двічі не можна оголосити:
namespace a {
auto _ = f(); // Ок
auto _ = f(); // Помилка
}Все логічно, короч 🤡 Ні, заждіть, це не жарт. Все справді логічно, якщо над цим поміркувати достатньо довго! Але капець, як же втомлює тримати подібні нюанси в голові весь час.
З іншого боку шанси, що це увійде в C++26, все одно низькі ) Може в C++32…