std::ignore со структурированными привязками?
Прелюдия:
std::tuple<int, int, int> f();
std::tuple<int, int, float, int> g();
C++ 1z введет синтаксис для структурированных привязок, который позволит писать вместо
int a, b, c;
std::tie(a, b, c) = f();
что-то вроде
auto [a, b, c] = f();
Тем не мение, std::tie
также разрешено указывать std::ignore
игнорировать определенные компоненты, например:
std::tie(a, b, std::ignore, c) = g();
Будет ли возможно сделать что-то подобное, используя новый синтаксис структурированных привязок? Как это будет работать?
5 ответов
Предложение по структурированным привязкам содержит специальный раздел, отвечающий на ваш вопрос ( P0144R2):
3.8 Должен ли быть способ явно игнорировать компоненты?
Мотивация - заставить замолчать предупреждения компилятора о неиспользуемых именах. Мы думаем, что ответ должен быть "еще нет". Это не мотивировано вариантами использования (глушение предупреждений компилятора является мотивацией, но это не случай использования как таковой), и лучше оставить его, пока мы не вернемся к этому в контексте более общее предложение по сопоставлению с образцом, где это должно выпадать как особый случай.
Симметрия с
std::tie
предложил бы использовать что-то вродеstd::ignore
:tuple<T1,T2,T3> f(); auto [x, std::ignore, z] = f(); // NOT proposed: ignore second element
Тем не менее, это чувствует себя неловко.
Предвидение сопоставления с шаблоном в языке может означать подстановочный знак
_
или же*
, но так как у нас пока нет сопоставления с образцом, преждевременно выбирать синтаксис, который, как мы знаем, будет совместимым. Это чистое расширение, которое может подождать рассмотрения с сопоставлением с образцом.
Однако обратите внимание, что рабочий проект стандарта в настоящее время пересматривается соответствующими национальными органами (NB), и есть комментарий NB, запрашивающий эту функцию ( P0488R0, US100):
Объявления декомпозиции должны обеспечивать синтаксис для отбрасывания некоторых возвращаемых значений, так же как
std::tie
использованияstd::ignore
,
Будет ли возможно сделать что-то подобное, используя новый синтаксис структурированных привязок?
Нет. Вам просто нужно составить имя переменной, которая не будет упомянута позже.
В C++26 появится красивый заполнитель без имени (P2169R0) . Благодаря этой новой языковой функции наконец-то можно использовать_
как способ игнорировать переменные в выражении структурированной привязки. Подробную информацию о конструкции смотрите в связанном документе.
я обычно использую
_
который является допустимым идентификатором в C++, но выглядит так же, как, например, оператор подчеркивания Kotlin, который отбрасывает лямбда-параметры. В итоге вы получите хороший код, подобный этому
map([&](auto it) {
auto [_, deviceServiceXAddr] = it;
return deviceServiceXAddr;
});
Вот быстрый и грязный хак, но он будет работать только для одного подчеркивания в строке. (Использование source_location в C++20 может распространить его и на столбцы...):
#define __CONCAT(x,y) x ## y
#define _CONCAT(x,y) __CONCAT(x,y)
#define _ _CONCAT(__tmp_ignore_var_, __LINE__)
int main(int argc, char* argv[])
{
auto p = make_pair(2,"hello");
auto [_, b] = p;
auto [a, _] = p;
return 0;
}