Это отличный вопрос. Это побудило меня посмотреть, есть ли какой-либо способ определить сущность во время компиляции, используя выражение constexpr.
Оказалось, что без препроцессорных трюков это невозможно, потому что нет возможности превратить целое число в последовательность байтов (через приведения или объединения) при оценке в контексте constexpr.
Однако оказывается, что в НКУ, простая проверка во время выполнения получает оптимизированную прочь при компиляции с -O2, так что это на самом деле оптимально эффективным:
#include <cstdint>
#include <iostream>
constexpr bool is_little_endian()
{
union endian_tester {
std::uint16_t n;
std::uint8_t p[4];
};
constexpr endian_tester sample = {0x0102};
return sample.p[0] == 0x2;
}
template<class Int>
Int to_little_endian(Int in)
{
if (is_little_endian()) {
return in;
}
else {
Int out = 0;
std::uint8_t* p = reinterpret_cast<std::uint8_t*>(std::addressof(out));
for (std::size_t byte = 0 ; byte < sizeof(in) ; ++byte)
{
auto part = (in >> (byte * 8)) & 0xff;
*p++ = std::uint8_t(part);
}
return out;
}
}
int main()
{
auto x = to_little_endian(10);
std::cout << x << std::endl;
}
вот выход ассемблера при компиляции на платформа intel (little-endian):
main:
subq $8, %rsp
#
# here is the call to to_little_endian()
#
movl $10, %esi
#
# that was it - it's been completely optimised away
#
movl std::cout, %edi
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
movq %rax, %rdi
call std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)
xorl %eax, %eax
addq $8, %rsp
ret
Что вы пытаетесь достичь? Если вы не делаете какое-то фанковое литье и разыменование указателей на целые числа разных размеров, вам не нужно беспокоиться о энтиансе. См. Также этот вопрос в разделе ["htonl() vs __builtin_bswap32()"] (http://stackoverflow.com/questions/21527957/htonl-vs-builtin-bswap32), в котором говорится об альтернативных способах байтов. – Jens
Если вам нужно возиться с endianess, вы уже ступите в области «не переносимые». Таким образом, изолируйте это так, чтобы остальная часть вашего кода работала с подходящими абстракциями, а для небольших платформ реализованы небольшие мелкие *** реализационные реализации платформы. –