我想创建这样一个结构:
struct Arrays{
typedef unsigned char byte_t;
std::array<byte_t, X>& get(int x, int y)
{
switch(x){
case 1: return arr_1.at(y);
case 2: return arr_2.at(y);
... up to ...
case 50: return arr_50.at(y);
default: break;
}
}
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;
};
我知道
std::array<byte_t, 1>
和
std::array<byte_t, 2>
是不同的结构,所以这是不可能的。我怎样才能以不同的方式管理它?我是否必须从方法中返回byte_t*
?
答案 0 :(得分:2)
正如之前的评论所说,数组大小是编译时常量。实现此目的的唯一方法是将x
作为模板参数传递。以下怎么样? (为方便起见,我已经定义了一个类vector_of_arrays
来保存你的向量arr_1
到arr_50
,这样我就可以通过数字来引用每个向量而不必切换和给出一个名字)
#include <array>
#include <type_traits>
#include <vector>
template <typename type, size_t max_size>
class vector_of_arrays : public std::vector<std::array<type, max_size>>
{
private:
vector_of_arrays<type, max_size - 1> _next;
public:
template <size_t size>
typename std::enable_if<(size < max_size), vector_of_arrays<type, size>&>::type
get_vector_for_size()
{
return _next.get_vector_for_size<size>();
}
template <size_t size>
typename std::enable_if<(size == max_size), vector_of_arrays<type, size>&>::type
get_vector_for_size()
{
return *this;
}
};
template <typename type>
class vector_of_arrays<type, 1> : public std::vector<std::array<type, 1>>
{
public:
template <size_t size>
typename std::enable_if<(size == 1), vector_of_arrays<type, size>&>::type
get_vector_for_size()
{
return *this;
}
};
struct arrays
{
typedef unsigned char byte_t;
vector_of_arrays<byte_t, 50> va;
template <size_t x>
std::array<byte_t, x>& emplace_array()
{
va.get_vector_for_size<x>().emplace_back();
return *(va.get_vector_for_size<x>().end() - 1);
}
template <size_t x>
std::array<byte_t, x>& get(int y)
{
return va.get_vector_for_size<x>().at(y);
}
};
要测试此代码,您可以执行类似
的操作arrays foo;
auto& arr1 = foo.emplace_array<3>();
arr1[0] = 1.;
arr1[1] = 2.;
arr1[2] = 3.;
auto& arr2 = foo.get<3>(0);
std::cout << arr2[0] << ' ' << arr2[1] << ' ' << arr2[2] << std::endl;
答案 1 :(得分:1)
首先,你违反了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;
其中AutoTuple<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
50
个std::vector
个std::array
,每个1
50
byte
到50
{{1} }}第
这比std::get<7>(my_tuple)
行要少得多,虽然这很难让它工作并理解它,但这意味着代码是统一的并且生成一次:一个机会的可能性要小得多特定的行是错误的,一次出现错误的可能性要大得多。您可以使用编译时值通过100
提取第n个元素。哦,如果你想要10
或50
而不是contiguous_range
?改变一个常数。
接下来,基本上是一对装扮指针的N
结构为您提供了一种类型擦除的方式来查看contiguous_range
元素的数组(或其他缓冲区),如{{3 }}
现在,您可以手动编写big switch语句,也可以构建一个函数指针表来提取// 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];
}
};
并自动构建它。
N
并构建一个包含50个数组的数组(每个数组都有不同的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
然后您可以使用运行时参数进行查找,调用它,并获得连续数组{{1}}的类型擦除实例。
非代码开销是50个指针(用于查找表),3个指针(用于包含向量)。
你永远不会做相同代码的cpoy /粘贴50次,每次更改一个数字,其中一个有一个轻微的拼写错误,产生一个微妙的fenceposting错误,只发生在一个不明显的,难以仅在发布模式下重现测试用例。