Date: Mon, 15 May 2023 10:30:55 +0100
#include <bit> // byteswap, endian::native/little
#include <concepts> // integral
#include <type_traits> // has_unique_object_representations_v
namespace std {
template<std::integral T>
constexpr T ntoh(T const value) noexcept
{
static_assert(std::has_unique_object_representations_v<T>,
"T may not have padding bits");
if constexpr ( std::endian::native == std::endian::big ) return value;
else return std::byteswap<T>(value);
}
template<std::integral T> constexpr T hton(T const value) noexcept
{ return ntoh<T>(value); }
}
Although personally I'd be more comfortable for the parameter to be
std::type_identity_t<T> so that you have to explicitly specify the
type:
cout << "Number: " << ntoh<uint16_t>(65029) << endl;
#include <concepts> // integral
#include <type_traits> // has_unique_object_representations_v
namespace std {
template<std::integral T>
constexpr T ntoh(T const value) noexcept
{
static_assert(std::has_unique_object_representations_v<T>,
"T may not have padding bits");
if constexpr ( std::endian::native == std::endian::big ) return value;
else return std::byteswap<T>(value);
}
template<std::integral T> constexpr T hton(T const value) noexcept
{ return ntoh<T>(value); }
}
Although personally I'd be more comfortable for the parameter to be
std::type_identity_t<T> so that you have to explicitly specify the
type:
cout << "Number: " << ntoh<uint16_t>(65029) << endl;
Received on 2023-05-15 09:31:08