debugcppMinor
A template-fixed-size unsigned integer class
Viewed 0 times
templatesizeunsignedfixedclassinteger
Problem
For some reason or another, I want to have available unsigned integers of sizes other than 1, 2, 4 and 8 (e.g. an unsigned integer with 3 bytes). For most platforms, compilers don't make those available; so - I rolled my own.
Other than asking for a general review, I will also pose a few specific questions / requests for guidance.
```
#ifndef UINT_H_
#define UINT_H_
#include
#include
#include
#include
#include // for memcpy and memset
namespace util {
/**
* A hopefully-fast integer-like class with arbitrary size
*
* @note Heavily dependent on compiler optimizations...
* @note For now, assumes little-endianness
* @note For now, limited to small sizes
*
*/
template
class uint_t final
{
static_assert(N ::fast;
using least_builtin_type = typename boost::int_t::least;
protected: // data members
value_type value; // Note it is _not_ necessarily aligned
public: // constructors
uint_t() noexcept = default;
uint_t(const uint_t& x) noexcept = default;
uint_t(uint_t&& x) noexcept = default;
protected: // building blocks for converting ctors, assignments and conversion operators
/ The next two methods are buggy, see @Deduplicator's answer /
template
uint_t& assign (I x) noexcept
{
if (sizeof(I)
I as_integer() const noexcept
{
I result;
if (sizeof(I)
uint_t& assign(I x) noexcept
{
auto x_bytes = (const byte* const) &x;
for (auto j = 0; j
I as_integer() const noexcept
{
I result;
if (sizeof(I) > N) { result = 0; }
auto result_bytes = (byte* const) &result;
for (auto j = 0; j (x); }
uint_t(signed char x) noexcept { assign(x); }
uint_t(unsigned char x) noexcept { assign(x); }
uint_t(short x) noexcept { assign(x); }
uint_t(unsigned short x) noexcept { assign(x); }
uint_t(int x) noexcept { assign(x); }
uint_t(unsigned x) noexcept { assig
Other than asking for a general review, I will also pose a few specific questions / requests for guidance.
```
#ifndef UINT_H_
#define UINT_H_
#include
#include
#include
#include
#include // for memcpy and memset
namespace util {
/**
* A hopefully-fast integer-like class with arbitrary size
*
* @note Heavily dependent on compiler optimizations...
* @note For now, assumes little-endianness
* @note For now, limited to small sizes
*
*/
template
class uint_t final
{
static_assert(N ::fast;
using least_builtin_type = typename boost::int_t::least;
protected: // data members
value_type value; // Note it is _not_ necessarily aligned
public: // constructors
uint_t() noexcept = default;
uint_t(const uint_t& x) noexcept = default;
uint_t(uint_t&& x) noexcept = default;
protected: // building blocks for converting ctors, assignments and conversion operators
/ The next two methods are buggy, see @Deduplicator's answer /
template
uint_t& assign (I x) noexcept
{
if (sizeof(I)
I as_integer() const noexcept
{
I result;
if (sizeof(I)
uint_t& assign(I x) noexcept
{
auto x_bytes = (const byte* const) &x;
for (auto j = 0; j
I as_integer() const noexcept
{
I result;
if (sizeof(I) > N) { result = 0; }
auto result_bytes = (byte* const) &result;
for (auto j = 0; j (x); }
uint_t(signed char x) noexcept { assign(x); }
uint_t(unsigned char x) noexcept { assign(x); }
uint_t(short x) noexcept { assign(x); }
uint_t(unsigned short x) noexcept { assign(x); }
uint_t(int x) noexcept { assign(x); }
uint_t(unsigned x) noexcept { assig
Solution
There is only ever a reason to have a move-ctor / move-assignment if that is more efficient than copy-ctor / copy-assignment, or the only one of the two which is valid.
You probably want to zero non-assigned bytes, and copy assigned bytes.
Currently, you zero and then overwrite some bytes and access out-of-bounds if the source is smaller than the destination.
You might want to write normal de- and en-coding code which has the same codepaths for little- as for big-endian.
.assign is wrong.You probably want to zero non-assigned bytes, and copy assigned bytes.
Currently, you zero and then overwrite some bytes and access out-of-bounds if the source is smaller than the destination.
You might want to write normal de- and en-coding code which has the same codepaths for little- as for big-endian.
// Example:
unsigned in;
unsigned char out[4];
for(int i = 0; i >= 8;
}Code Snippets
// Example:
unsigned in;
unsigned char out[4];
for(int i = 0; i < 4; i++) {
out[i] = in & 0xff;
in >>= 8;
}Context
StackExchange Code Review Q#151543, answer score: 2
Revisions (0)
No revisions yet.