cpp-ru / ideas

Идеи по улучшению языка C++ для обсуждения
https://cpp-ru.github.io/proposals
Creative Commons Zero v1.0 Universal
88 stars 0 forks source link

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

Open kirillgrachoff opened 3 years ago

kirillgrachoff commented 3 years ago

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

Иногда очень хочется делать 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&, чтобы не вызвать лишний конструктор копирования.

GeorgiiFirsov commented 3 years ago

Это имеет смысл возможно только при наличии каких-либо других аргументов, помимо указанного пака параметров, хотя и тут выкрутиться можно. Что же касается случая, приведенного выше, то оно, начиная с 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);

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

kirillgrachoff commented 3 years ago

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

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