Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Добавить возможности кортежей к агрегатам #26

Open
Neargye opened this issue Mar 12, 2021 · 3 comments
Assignees
Labels
В работе Над идеей идёт активная работа в рамках РГ21

Comments

@Neargye
Copy link
Member

Neargye commented Mar 12, 2021

Перенос предложения: голоса +6, -2
Автор идеи: Антон Полухин @apolukhin

std::tuple и std::pair отлично подходяд для обобщённого программирования, однако у них есть недостатки. Во первых, использующий их код сложно читать и понимать:

struct auth_info_aggreagte {
    std::int64_t id;
    std::int64_t session_id;
    std::int64_t source_id;
    std::time_t valid_till;
};

using auth_info_tuple = std::tuple<
    std::int64_t,
    std::int64_t,
    std::int64_t,
    std::time_t
>;

Объявление через структуру намного понятнее, видно за что какое поле отвечает, что в нём хранится. Использование структур тоже более понятное: return std::get<1>(value); сравните с return value.session_id;

Во вторых, агрегаты предоставляют более эффективные операции копирования, присваивания и перемещения:

template <class T>
constexpr bool validate() {
    static_assert(std::is_trivially_move_constructible_v<T>);
    static_assert(std::is_trivially_copy_constructible_v<T>);
    static_assert(std::is_trivially_move_assignable_v<T>);
    static_assert(std::is_trivially_copy_assignable_v<T>);
    return true;
}

constexpr bool tuples_fail = validate<auth_info_tuple>(); // Проваливает большинство проверок
constexpr bool aggregates_are_ok = validate<auth_info_aggreagte>();

Из-за вышеозвученных причин, многие компании рекомендуют использовать агрегаты вместо кортежей.

Однако, мы не можем использовать агрегаты в обобщённом коде (разве что мы воспользуемся библиотекой Boost.PFR):

namespace impl {
    template <class Stream, class Result, std::size_t... I>
    void fill_fileds(Stream& s, Result& res, std::index_sequence<I...>) {
        (s >> ... >> std::get<I>(res));
    }
}

template <class T>
T ExecuteSQL(std::string_view statement) {
    std::stringstream stream;
    // some logic that feeds data into stream

    T result;
    impl::fill_fileds(stream, result, std::make_index_sequence<std::tuple_size_v<T>>());
    return result;
}

constexpr std::string_view query = "SELECT id, session_id, source_id, valid_till FROM auth";
const auto tuple_result = ExecuteSQL<auth_info_tuple>(query);
const auto aggreagate_result = ExecuteSQL<auth_info_aggreagte>(query); // does not compile

// Можно проверить на https://godbolt.org/z/y49lya

Добавив функциональность кортежей к агрегатам мы получим все преимущества кортежей, не потеряв преимуществ агрегатов. Мы получим именованные кортежи.

@Neargye
Copy link
Member Author

Neargye commented Mar 12, 2021

yndx-antoshkka 11 января, 19:14
https://wg21.link/P2141 - предложение на английском, с доп примерами.

@apolukhin apolukhin added the В работе Над идеей идёт активная работа в рамках РГ21 label Mar 12, 2021
@apolukhin apolukhin self-assigned this Mar 17, 2021
@SashaBorisov
Copy link

Так а что это за возможности? Вспоминаю только доступ по индексу и всю обвязку для этого.

@tomilov
Copy link

tomilov commented Nov 6, 2022

Мне кажется многие проблемы бы решил некий оператор "распаковки в список аргументов функции".

struct X { int a; double b; float c; };
X x{1, 2.0, 3.0f};
auto make_tuple = [](auto &&... v) {
    return std::make_tuple(std::forward<decltype(v)>(v)...);
};
auto tuple = make_tuple(@x);  // @ - это предполагаемый оператор
auto forward_as_tuple = [](auto &&... v) {
    return std::forward_as_tuple(std::forward<decltype(v)>(v)...);
};
auto refs = forward_as_tuple(@x);
auto tie = [](auto &... v) {
    return std::tie(v...);
};
auto lrefs = tie(@x);

Если бы structured bindings завезли в таком виде в своё время, то было бы намного меньше вопросов, мне кажется.

Оператор я бы сделал постфиксным унарным .* или .*... (ну и ->* или ->*... для единообразия).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
В работе Над идеей идёт активная работа в рамках РГ21
Projects
None yet
Development

No branches or pull requests

4 participants