如何使用c ++模板有效地推出序列

Axe*_*xel 10 c++ templates c++11 stdtuple

我有一个复杂的类型,C取决于我在(长度有界)序列中需要的模板参数.constexpr函数next()可用于从C_n - > C_n + 1开始.由于每个序列元素都有不同的类型,我使用a std::tuple来存储结果.这些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;
}
Run Code Online (Sandbox Code Playgroud)

问题是我的mkTuple()功能似乎太昂贵,以至于我很快遇到了编译器内存不足的问题.事实上,g++ -ftime-report ...报告>模板实例化的使用量为1GB.这个数字很快(指数地?)随着序列长度的增加而上升.

我怀疑std::tuple实例化需要std::tuple_cat成为inflater.有没有人知道如何更有效地推出序列?

Thx提前!

Vit*_*meo 6

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 {};
}
Run Code Online (Sandbox Code Playgroud)

然后替换使用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>;
};
Run Code Online (Sandbox Code Playgroud)

最后,转换到最后:

using tMyTuple = typename mkTuple<C, 16, 2, 64>::tuple::as_tuple;
Run Code Online (Sandbox Code Playgroud)

直播wandbox示例

输出:

序列长度= 64

元组[4] .size()= 24