|
|
![]() | Imperfect C++ Practical Solutions for Real-Life Programming By Matthew Wilson |
| Table of Contents | |
| Chapter 29. Arithmetic Types |
29.1. Class DefinitionBefore we get stuck into the minutiae, we'll just take a look at the class definition. I decided, in order to avoid confusion with the two extant member variables lowerVal and upperVal, to use protected inheritance and derive a new type UInteger64. This is so we can cheat and use a union of uinteger64 and a uint64_t in order to perform the arithmetic. This relies on the correct layout of the two members in the structure, as follows:[1]
Listing 29.1.
struct uinteger64
{
#if defined(ACMELIB_LITTLE_ENDIAN)
uint32_t lowerVal;
uint32_t upperVal;
#elif defined(ACMELIB_BIG_ENDIAN)
uint32_t upperVal;
uint32_t lowerVal;
#else
# error Need to discriminate further . . .
#endif /* endian */
};
This allows us to do the following monstrosity, which, as I said, is merely for expediency for this specific type, rather than a technique one would use for large integers in general: Listing 29.2.class UInteger64 : protected uinteger64 { public: typedef union { uint64_t i; uinteger64 s; } ui64_union; ui64_union &get_union_() { uinteger64 *p1 = this; ui64_union *p2 = reinterpret_cast<ui64_union*>(p1); return *p2; } ui64_union const &get_union_() const; . . . It's not the way you'd start out and design a large integer class from scratch, where you'd not have the option of using a higher fundamental type in anything larger than 64 bits. The test harness for this chapter consists of a template function within which a variety of numeric operations are performed. We'll go through them all, and see the ramifications for the design of our class. |
|
|