ideas icon indicating copy to clipboard operation
ideas copied to clipboard

Structure bindings и structure matching в аргументах функции

Open kirillgrachoff opened this issue 4 years ago • 2 comments

Распаковка структур данных прямо в аргументах функции

Иногда очень хочется делать structure matching в аргументах функции.

В C++ есть передача аргументов по значению. Т.е. конструктор копирования выполняется до кода функции.

Хотелось бы делать что-то похожее на structure binding.

using Type = std::tuple<int, char, std::string>;
void foo(Type& [a, b, c]) {
    std::cout << a << ' ' << b << ' ' << c << '\n';
}

Здесь type(a) == int&; type(b) == char&; type(c) = std::string&.

void foo(Type [a, b, c]) {
    std::cout << a << ' ' << b << ' ' << c << '\n';
}

Здесь type(a) == int; type(b) == char; type(c) == std::string

void foo(Type&& [a, b, c]) {
    std::cout << a << ' ' << b << ' ' << c << '\n';
}

Здесь type(a) == int&&; type(b) == char&&; type(c) == std::string&&

Предложение

Ввести такой синтаксис.

Почему это удобно

Вы не заводите новых имён в функции. Без этого нужно было бы писать так:

void foo(Type type) {
    auto& [a, b, c] = type;
    // ...
}
void foo(Type& type) {
    auto& [a, b, c] = type;
    // ...
}

Проблема налицо: появляется новое имя type и можно забыть написать auto&, чтобы не вызвать лишний конструктор копирования.

kirillgrachoff avatar Apr 25 '21 18:04 kirillgrachoff

Это имеет смысл возможно только при наличии каких-либо других аргументов, помимо указанного пака параметров, хотя и тут выкрутиться можно. Что же касается случая, приведенного выше, то оно, начиная с C++17 решается при помощи std::apply:

void foo(int a, char b, const std::string& c) { ... }

std::tuple<int, char, std::string> tpl(...);
std::apply(foo, tpl);

Кроме того, приведенные в посте примеры сильно ограничивают типы аргументов. Так, например, не получится сделать, чтобы инты передавались по значению, а строки - по ссылке.

GeorgiiFirsov avatar Apr 29 '21 18:04 GeorgiiFirsov

Для передачи по ссылке и т.д. можно подключить что-то из предыдущего предложения #447. Но тогда непонятно, как копировать и где хранить объект.

К тому же, std::apply работает только для std::tuple, а здесь предлагается реализовать это для всех типов, где есть structured binding. (в т.ч. и своих)

kirillgrachoff avatar May 03 '21 00:05 kirillgrachoff