Используйте boost::variant
и gsl::span
.
enum data_type { INT16 = 0, INT32, UINT64, FLOAT, TIMESTAMP };
struct buffer {
data_type element_type;
size_t size; // in elements of element_type, not bytes
void* data;
};
template<class...Ts>
using var_span = boost::variant< gsl::span< Ts > ... >;
using buffer_span = var_span< std::int16_t, std::int32_t, std::uint64_t, float, ??? >;
buffer_span to_span( buffer buff ) {
switch (buff.element_type) {
case INT16: return gsl::span<std::int16_t>( (std::int16_t*)buff.data, buff.size );
// etc
}
}
теперь вы можете
auto span = to_span( buff );
, а затем перейдите к span для безопасного доступа к буферу данных.
Написание посетителей менее болезненно в c ++ 14 из-за [](auto&&)
лямбды, но выполнимо в c ++ 11 .
Написание template<class...Fs> struct overloaded
также может облегчить написание посетителей. Существует множество реализаций.
Если вы не можете использовать boost
, вы можете конвертировать to_span
в visit_span
и заставить его принять посетителя.
Если вы не можете использовать gsl
, написание собственного span
тривиально.
visit_span( buff, overload(
[](span<int16_t> span) { /* code */ },
[](span<int32_t> span) { /* code */ },
// ...
));
или
struct do_foo {
template<class T>
void operator()(span<T> span) { /* code */ }
};
visit_span( buff, do_foo{captures} );