我有一个计算CRC64并将其返回为uint64_t
的函数:
static inline uint64_t crc64(uint64_t crc, const uint8_t *s, size_t l)
{
const uint8_t * end = s + l;
for (const uint8_t * p = s; p != end; ++p)
{
const uint8_t byte = *p;
crc = crc64_tab[(uint8_t)crc ^ byte] ^ (crc >> 8);
}
return crc;
}
,我想将结果转换为std::array<sizeof(uint8_t)>
,并使它独立于字节序(小/大字节序)。有没有简单而优雅的方法可以在C ++中做到这一点?
是否有一个简单的模板函数可用于所有算术类型,例如uintN_t
?
答案 0 :(得分:1)
是否可以有一个简单的模板函数适用于uintN_t之类的所有算术类型?
#include <cstddef>
#include <cstdint>
#include <array>
template< typename T >
std::array<std::uint8_t, sizeof(T)> to_array(T value)
{
std::array<std::uint8_t, sizeof(T)> result;
for (std::size_t i{ sizeof(T) }; i; --i)
result[i - 1] = value >> ((sizeof(T) - i) * 8);
return result;
}
答案 1 :(得分:0)
我认为我倾向于反转依赖关系,并创建一种类型的“ bytewise_accumulation”概念。
它似乎在gcc8上生成了不错的代码:
#include <cstddef>
#include <cstdint>
#include <type_traits>
// general case
template<class T>
struct bytewise_accumulator
{
template<class Arg, class F, class Acc>
constexpr decltype(auto) operator()(Arg value, F&& f, Acc acc) const
{
for(std::size_t i = 0 ; i < sizeof(T) ; ++i)
{
acc = f(acc, std::uint8_t(value));
value >>= 8;
}
return acc;
}
};
template<class T>
auto make_bytewise_accumulator(T&&)
{
return bytewise_accumulator<std::remove_reference_t<std::remove_const_t<T>>>();
}
// overload for c-arrays but others could be provided for std::array, vector, etc
template<class T, std::size_t N>
struct bytewise_accumulator<T[N]>
{
template<class F, class Acc>
constexpr decltype(auto) operator()(T(&value)[N], F&& f, Acc acc) const
{
for(auto&& x : value)
{
auto op = make_bytewise_accumulator(x);
acc = op(x, f, acc);
}
return acc;
}
};
template<
typename Acc,
typename T,
class F
>
constexpr decltype(auto) bytewise_accumulate(T&& value, F&& f, Acc acc)
{
auto op = make_bytewise_accumulator(value);
return op(value, f, acc);
}
// the actual crc function
auto crc64(std::uint64_t crc, std::uint8_t byte) -> std::uint64_t
{
extern std::uint64_t crc64_tab[256];
return crc64_tab[(uint8_t)crc ^ byte] ^ (crc >> 8);
}
// compute a crc of a series of objects
template<class...Ts>
auto compute_crc64(Ts&&...ts) -> std::uint64_t
{
auto crc = std::uint64_t(0);
((crc = bytewise_accumulate(ts, crc64, crc)), ...);
return crc;
}
// some tests...
extern int get_int();
extern void emit(std::uint64_t);
struct Data
{
int x;
int y;
unsigned long z;
char data[128];
};
// overload bytewise_accumulate for my custom type
template<
typename Acc,
class F
>
constexpr decltype(auto) bytewise_accumulate(Data const& d, F&& f, Acc acc)
{
acc = bytewise_accumulate(d.x, f, acc);
acc = bytewise_accumulate(d.y, f, acc);
acc = bytewise_accumulate(d.z, f, acc);
acc = bytewise_accumulate(d.data, f, acc);
return acc;
}
extern Data const& get_data();
int main()
{
auto i = get_int();
auto crc = compute_crc64(i);
emit(crc);
emit(compute_crc64(get_data()));
}