-
Notifications
You must be signed in to change notification settings - Fork 1
/
vec_offsets.hpp
137 lines (137 loc) · 2.74 KB
/
vec_offsets.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#ifndef VEC_OFFSETS_HPP_INCLUDED
#define VEC_OFFSETS_HPP_INCLUDED
#include <array>//and std::make_tuple, std::tuple
#include <boost/align/is_aligned.hpp>
#include <boost/align/align_up.hpp>
namespace vec_offsets_alignment=boost::alignment;
template
< typename T
, std::size_t Align=alignof(T)
//Requested alignment for T.
//Must be (some power of 2)*alignof(T)
>
struct
type_align
/**@brief
* Allow overalignment, Align for T
* to be specified in template args
* to vec_offsets.
*/
{
using type=T;
static constexpr std::size_t align=Align;
};
template
< typename T
>
struct
get_align
{
static constexpr std::size_t align=alignof(T);
};
template
< typename T
>
struct
get_type
{
using type=T;
};
template
< typename T
, std::size_t Align
>
struct
get_align
< type_align<T,Align>
>
{
static constexpr std::size_t align=Align;
};
template
< typename T
, std::size_t Align
>
struct
get_type
< type_align<T,Align>
>
{
using type=T;
};
template
< std::size_t N
>
using
over_aligns_t=
std::array
< std::size_t
, N
>
;
template
< std::size_t N
>
struct
vec_offsets_t
: std::array
< std::size_t
, N+2
>
{
vec_offsets_t()
{}
static constexpr std::size_t
i_size=N;
static constexpr std::size_t
i_align=i_size+1;
std::size_t size_all()const
{ return this->operator[](i_size);}
std::size_t align_all()const
{ return this->operator[](i_align);}
};
template
< typename... TypeAlign
>
constexpr
auto
vec_offsets
( std::size_t vec_size
)
/**@brief
* Calculate offsets in a char buffer for storing
* suitably aligned get_type<TypeAlign>::type... elements.
* Next to last value is is for the char buffer size.
* Last value is maximum of get_align<TypeAlign>::align...
*/
{
std::size_t const num_types=sizeof...(TypeAlign);
using offsets_t=vec_offsets_t<num_types>;
offsets_t offsets_v;
std::size_t sizes[num_types]={(vec_size*sizeof(typename get_type<TypeAlign>::type))...};
std::size_t aligns[num_types]={get_align<TypeAlign>::align...};
std::size_t i_type=0;
std::size_t max_align=aligns[i_type];
offsets_v[i_type]=0;
auto
nxt_offset=[&](std::size_t align_i)
{
offsets_v[i_type]=vec_offsets_alignment::align_up
( offsets_v[i_type-1]+sizes[i_type-1]
, align_i
);
};
for
( ++i_type
; i_type<num_types
; ++i_type
)
{
nxt_offset(aligns[i_type]);
max_align=std::max(max_align,aligns[i_type]);
}
nxt_offset(max_align);
offsets_v[offsets_t::i_align]=max_align;
return offsets_v;
}
#endif//VEC_OFFSETS_HPP_INCLUDED