首先,你违反了 DRY。
替换这个:
std::vector<std::array<byte_t, 1>> arr_1;
std::vector<std::array<byte_t, 2>> arr_2;
... up to ....
std::vector<std::array<byte_t, 50>> arr_50;
有类似的东西:
template<typename Pack, unsigned X> struct append;
template<template<unsigned...>class Pack, unsigned... Xs, unsigned X>
struct append<Pack<Xs...>, X> {
typedef Pack<Xs..., X> type;
};
template<typename Pack, unsigned X> using Append=typename append<Pack,X>::type;
template<unsigned N, template<unsigned>class Contents>
struct auto_tuple {
typedef Append< typename auto_tuple<N-1, Contents>::type, Contents<N-1> > type;
};
template<template<unsigned>class Contents>
struct auto_tuple<0, Contents> {
typedef std::tuple<> type;
};
template<unsigned N, template<unsigned>class Contents>
using AutoTuple = typename auto_tuple<N,Contents>::type;
whereAutoTuple<N, Contents>
适用于并从中0
生成一个。写:N-1
Contents
std::tuple
template<typename T, unsigned N>
using vec_of_array = std::vector<std::array<T, N>>;
template<unsigned N>
using vec_of_byte_array = vec_of_array<byte_t, N>;
template<unsigned N>
using get_nth_byte_array = vec_of_byte_array<N+1>;
你用它来填充你的tuple
喜欢:
typedef AutoTuple<50, get_nth_byte_array> my_tuple;
这是一个不同std::tuple
的s ,每个存储一个到s。50
std::vector
std::array
1
50
byte
这比行少得多50
,虽然这将更难让它工作和理解它,但这意味着代码是统一的并且生成一次:一个特定的行错误的可能性要小得多,而且远一次所有事情都出错的可能性更高。您可以使用编译时值通过std::get<7>(my_tuple)
. 哦,如果你想要100
或10
代替50
?改变一个常数。
接下来,contiguous_range
基本上是一对指针的结构为您提供了一种类型擦除的方式来查看N
元素的数组(或其他缓冲区),例如将未知大小的 std::array 传递给函数
现在,您可以手动编写大 switch 语句,也可以构建一个函数指针表来提取contiguous_range
并自动构建它。
// DataStorage is the tuple of std::vector of std::array
template<unsigned...> struct seq{};
template<unsigned max, unsigned... s> struct make_seq:make_seq<max-1, max-1, s...> {};
template<unsigned... s> struct make_seq<0,s...>:seq<s...> {};
template<unsigned N>
struct get_array {
static contig_range<byte> get(DataStorage& data, unsinged idx) {
return ( std::get<N>( std::forward<Data>(data) )[idx];
}
};
并构建一个由 50 个数组组成的数组(每个数组都有一个不同的N
),存储在一个数组中:
typedef contig_range<byte> (*array_getter)( DataStorage&, unsigned idx );
template<unsigned N, unsigned... S>
std::array< array_getter, N > populate_array_helper( seq<S...> ) {
return { get_array<S>::get... };
}
template<unsigned N>
std::array< array_getter, N > populate_array() {
return populate_array_helper( make_seq<N>() );
}
然后您可以使用运行时参数来查找、调用它,然后您将获得byte
.
非代码开销是 50 个指针(用于查找表),3 个指针(用于包含向量)。
而且您永远不会对相同的代码进行 50 次 cpoy/paste 并且每次都更改一个数字,其中一个有轻微的拼写错误,会产生一个微妙的栅栏错误,该错误仅发生在一个晦涩难懂的、难以重现的测试用例中仅在发布模式下。