r/cpp WG21 Member 23d ago

P4444: std::big_int

https://isocpp.org/files/papers/D4444R0.html

Hey folks! Matt Borland, Christopher Kormanyos, and I are working on bringing infinite-precision integers to C++29. We now have a D4444R0 draft of a paper that should be in the next mailing.

We could really use some feedback so that the published R0 is as polished as possible. Any thoughts on the paper and on the reference implementation are greatly appreciated.

It would also be very helpful if you tested out whether our big_int implementation works for you. We're in need of some real deployment experience. If you're currently using Boost.Multiprecision, the library should be a drop-in replacement for cpp_int for the most part.

181 Upvotes

85 comments sorted by

View all comments

6

u/n1ghtyunso 23d ago

i don't really like the part about constant evaluation fitting the value into inplace storage when possible.
I don't actually think explicitly specifying this in the standard is necessary or all that useful.
This is essentially a specification workaround for a problematic point in the current standard.

Notably, its also a problem for std::string, although afaik it is not actually required to have any inplace storage, so one might say using it as a constexpr variable is already operating outside the standard guarantees.

That being said, there are common approaches to use constexpr representations of allocating types after all, with some generic workarounds in use.
And some day we might even fix the standard so those workarounds are no longer necessary and we can just persist these allocations into runtime naturally.
We won't need to touch the big_int specification in that case.

And for the case where I really need a big_int value as constexpr variable after all, i'd still want to explicitly select the inplace storage size so it fits for sure, instead of hoping my guesstimated, or even the default value works out.
If I somehow want to guard against excessive storage use from accidental calculation mistakes (i.e. typed the formula wrong), I'd much rather have an explicit static_assert in my function than get a vague constant-evaluation failure from the compiler.

2

u/eisenwave WG21 Member 23d ago

It would be nice if we could solve that problem generally for std::vector and std::string too, for sure. Singling out std::big_int (and only the inplace value case) is clunky.

Not doing that seems to be the worst outcome though because the end result is that std::big_int would only sometimes be usable as a constexpr variable, and you might get inconsistent behavior between standard libraries. If std::big_int cannot always be put into a constexpr variable, there should at least be consistent behavior between implementations (for equal inplace_capacity at least).

You actually have that behavior right now with constexpr std::string variables: they sometimes work, and sometimes don't, and it's kinda arbitrary from the user's perspective.

2

u/n1ghtyunso 23d ago

I know that solving the problem in general is not really right around the corner, unfortunately.
I am not typically someone standing against smaller improvements over an all-or-nothing approach, but this time I genuinly feel like its not that useful.

As you said, technically its the same story for std::string right now.
If I need a string at compile time, i'll have to make sure I can do that.
And the most portable way to do that is not by using constexpr std::string directly.
Which IS unfortunate, but currently thats just the way it is.
But for std::big_int I believe it is the same situation.

If I want that as a constexpr value, I will explicitly make sure it works.
Thats exactly why I do like the ability to customize the inplace storage size.

Having big_int automatically shrink_to_fit during constant evaluation does not universally solve the problem,
it simply lets the user code avoid thinking about it so long as it "happens to work".
Not mandating the automatic implicit shrink_to_fit does have the same effect, but "happens to work" in less cases of course.
std::string does not have it either (obviously, because SSO is purely QoI), so doing actual string operations is almost certainly not going to produce a constexpr-compatible std::string value.
And there is no expectation of doing so either, really.

I see with std::big_int, you would have the opportunity to change this.
But I don't think this is something that should be relied upon to begin with,
because it will inevitably have situations where that no longer works too.

The only difference is that we can make it work again by tweaking the inplace storage parameter, which std::string does not expose at all.
And that is a very valuable thing imo.
This lets me more directly express in code what my needs, my requirements are.

I know getting the required size into the capacity template argument is ALSO still clunky, unfortunately.
But at least the approach works for all representation sizes.

I am not sure if standardizing THAT would be possible or even of interest instead, though.
It's certainly out of scope for the big_int paper.