XRPLF/rippled

IOUAmount and zero

Opened this issue · 0 comments

IOUAmount has a special representation for zero, but the default constructor IOUAmount() has defaulted implementation, which does not land in that special representation. Some odd behavior I'm observing:

  1. A constant IOUAmount cannot be default constructed without braces.
IOUAmount const x; // error
IOUAmount y; // ok
IOUAmount const z{}; ok

The error:

/home/jfreeman/code/rippled/src/test/basics/IOUAmount_test.cpp:48:25: error: uninitialized 'const zzz' [-fpermissive]
   48 |         IOUAmount const zzz;
      |                         ^~~
In file included from /home/jfreeman/code/rippled/src/test/basics/IOUAmount_test.cpp:20:
/home/jfreeman/code/rippled/include/xrpl/basics/IOUAmount.h:43:7: note: 'const class ripple::IOUAmount' has no user-provided default constructor
   43 | class IOUAmount : private boost::totally_ordered<IOUAmount>,
      |       ^~~~~~~~~
/home/jfreeman/code/rippled/include/xrpl/basics/IOUAmount.h:60:5: note: constructor is not user-provided because it is explicitly defaulted in the class body
   60 |     IOUAmount() = default;
      |     ^~~~~~~~~
/home/jfreeman/code/rippled/include/xrpl/basics/IOUAmount.h:47:18: note: and the implicitly-defined constructor does not initialize 'int64_t ripple::IOUAmount::mantissa_'
   47 |     std::int64_t mantissa_;
      |                  ^~~~~~~~~
  1. A default-constructed IOUAmount compares equal to beast::zero, but not to an IOUAmount constructed with beast::zero. This is because the second comparison calls IOUAmount::operator== (IOUAmount const&), but the first calls operator== (T const&, beast::Zero const&) which defers to calling T::signum() and comparing to 0.
IOUAmount const z{};
z == beast::zero; // true
IOUAmount const zz(beast::zero);
z == zz; // false

I suspect we need to manually implement the default constructor to fix both of these, but can anyone explain the first behavior?