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

yndx-antoshkka
yndx-antoshkka

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

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

3
рейтинг
в разработке
1 комментарий
yndx-antoshkka

wg21.link/P2141 - предложение на английском, с доп примерами.

yndx-antoshkka
Другие идеи
Группа создана, чтобы собирать предложения к стандарту C++, организовывать их внутренние обсуждения, помогать готовить их для отправки в комитет и защищать на общих собраниях в рабочей группе по С++ Международной организации по стандартизации (ISO).
Все предложения