Как эффективно развернуть последовательность с помощью шаблонов c++

у меня сложный тип C в зависимости от параметра шаблона, который мне нужен В (длина ограничена) последовательности. Функция функция constexpr next() доступен для перехода от C_n - > C_n+1. Поскольку каждый элемент последовательности имеет другой тип, я использую std::tuple для сохранения результатов. The mkTuple() функции позаботьтесь о (ограниченном) развертывании последовательности.

вот упрощенный пример того, что я сделал (с помощью std::array как заполнитель для моего более сложного C):

#include <array>
#include <tuple>
#include <iostream>


template<std::size_t OFFSET>
using C=std::array<uint8_t, OFFSET>;

static
constexpr
std::size_t
next(const std::size_t START, const std::size_t DISTANCE)
{
    return START + DISTANCE;
}


template<template<std::size_t OFFSET> class CONTENT, std::size_t START, std::size_t DISTANCE, std::size_t SEQ_LENGTH>
struct mkTuple
{
    using _LT = CONTENT<START>;
    using _RT = typename mkTuple<CONTENT, next(START, DISTANCE), DISTANCE, SEQ_LENGTH - 1>::tuple;
    using tuple=decltype(std::tuple_cat(std::make_tuple(_LT()), _RT()));
};


template<template<std::size_t OFFSET> class CONTENT, std::size_t START, std::size_t DISTANCE>
struct mkTuple<CONTENT, START, DISTANCE, 1>
{
    using _LT = CONTENT<START>;
    using tuple = std::tuple<_LT>;
};


int
main()
{
    using tMyTuple = typename mkTuple<C, 16, 2, 64>::tuple;

    const std::size_t iTupleLength = std::tuple_size<tMyTuple>::value;
    std::cout << "Sequence length =  " << iTupleLength << std::endl;

    const tMyTuple myTuple;
    std::cout << "Tuple[4].size() =  " << std::get<4>(myTuple).size() << std::endl;

    return 0;
}

проблема в том, что мой mkTuple() функции кажутся дорогими для памяти soo, что я быстро сталкиваюсь с проблемой компилятора из памяти. На самом деле g++ -ftime-report ... отчеты >использование 1 ГБ для создания экземпляров шаблонов. И это число быстро (экспоненциально?) возрастает с ростом длины последовательности.

Я подозреваю std::tuple экземпляр требуется для std::tuple_cat должен быть насос. У кого-нибудь есть хорошая идея, как развернуть последовательность более эффективно?

Thx заранее!

1 ответов


кажется std::tuple является излишним для вашего сценария - вы можете работать только на уровне типа-системы, а затем преобразовать в std::tuple В конце.

С std::tupleреализация большая и сложная, неудивительно, что она будет медленной для большого количества экземпляров. Ролл свой typelist:

template <typename... Ts>
struct typelist 
{ 
    using as_tuple = std::tuple<Ts...>; 
};

template <typename... As, typename... Bs>
constexpr auto typelist_cat(typelist<As...>, typelist<Bs...>) 
    -> typelist<As..., Bs...> 
{
    return {};
}

затем замените использование std::tuple:

template<template<std::size_t OFFSET> class CONTENT, std::size_t START, std::size_t DISTANCE, std::size_t SEQ_LENGTH>
struct mkTuple
{
    using _LT = CONTENT<START>;
    using _RT = typename mkTuple<CONTENT, START + DISTANCE, DISTANCE, SEQ_LENGTH - 1>::tuple;
    using tuple = decltype(typelist_cat(typelist<_LT>{}, _RT{}));
};


template<template<std::size_t OFFSET> class CONTENT, std::size_t START, std::size_t DISTANCE>
struct mkTuple<CONTENT, START, DISTANCE, 1>
{
    using _LT = CONTENT<START>;
    using tuple = typelist<_LT>;
};

и, наконец, преобразовать в конце:

using tMyTuple = typename mkTuple<C, 16, 2, 64>::tuple::as_tuple;

live wandbox пример

выход:

длина последовательности = 64

Кортеж[4].размер() = 24