I'm writing a large fixed-size integer type that is made up of multiple uint64_t
s, like in the (simplified) example below. I would like my type to behave like the built-in integer types, which means (among other things) that:
- it should be uninitialized if you don't assign a value to it, and
- it should accept widening from other built-in integer types.
It appears to me, however, that one cannot write a type that simultaneously satisfies both properties. This is because property 1 requires the type to be an aggregate, which means it must have no constructors, and we need a constructor to implement property 2.
Is there any way to write a large integer type that satisfies both properties?
#include <array>
#include <cstdint>
struct uint128_t{
std::array<uint64_t, 2> data;
};
int main(){
uint128_t x; // uninitialized (good)
uint128_t y = 100; // can we make this work while ensuring that the previous line still works?
}
CodePudding user response:
A constructor such as uint128_t() {}
will leave your array uninitialized by default. Ability to leave members uninitalized has nothing to do with being an aggregate.
But there's a better option: uint128() = default;
. It will cause uint128_t x;
to be uninitialized, but uint128_t x{};
will be zeroed, just like with built-in types.
CodePudding user response:
This is because property 1 requires the type to be an aggregate, which means it must have no constructors
No, it could have empty constructors
class uint128_t{
public:
// this is an empty constructor, it does not initializes data
uint128_t() {};
// calling this ctor will create an object with an initial value "val"
uint128_t(uint64_t val)
:data{0, val} {}
// for larger numbers
uint128_t(std::string_view src) {
// implement it yourself
}
private:
std::array<uint64_t, 2> data;
};