Date: Sat, 20 Mar 2021 12:26:47 +0100
Hi,
I have an idea for an addition to the standard library. Before creating a
formal paper, I wanted to ask what do you think and whether you remember a
similar proposal and discussion.
Below you can find a kind of beginning of the formal paper. I did not write
wording. I will do it when (and if) creating the formal paper.
Please find Markdown and PDF file in the attachment, if you prefer
formatted text.
I have an idea for an addition to the standard library. Before creating a
formal paper, I wanted to ask what do you think and whether you remember a
similar proposal and discussion.
Below you can find a kind of beginning of the formal paper. I did not write
wording. I will do it when (and if) creating the formal paper.
Please find Markdown and PDF file in the attachment, if you prefer
formatted text.
--- # Abstract This paper is meant to propose an addition to the standard library. New compile time functions indicating how many characters can be produced when formatting any possible value of a given integer or floating point. Example question: How many characters can be produced when formatting a value of type `int`, with base `10`? Possible answer: On an architecture that uses two's completion for signed integers, `sizeof(int) == 8`, `CHAR_BIT == 8` -> the answer is `20`. `19` digits and possibly a minus sign character. # Motivation With `<char_conv>` it is easy to convert values to characters without dynamic memory allocation. E.g. create a buffer 'on the stack' and use it. But, it is not so easy to know how big the buffer has to be. If one wants to calculate the exact result, there are lots of factors to consider: `sizeof(T)`, `is_signed`, `CHAR_BIT`, signed integers representation, floating-point arithmetic and more. It is common to create a big buffer, just to be sure the value fits there. This could be avoided with the help of the standard library and the compiler. All the necessary information is known at compile time and when you know it, it is fairly easy to calculate the result. # Available options for creating the buffer * First and the most obvious option is to create a big buffer and don't care. Again, how big the buffer has to be? `64`, `128`? What about floating points? `std::numeric_limits<>::lowest` of `float` takes `40` characters to format, `double` - `310` and of `long double` - `4934` (considering `std::numeric_limits<>::is_iec559 == true` and calling `std::to_chars()` with `std::chars_format::fixed`). * `<limits>` provides lots of information. There is `numeric_limits<>::digits10` which is not quite what we want and is bound to base `10`. There is `numeric_limits<>::digits` which can be used, but is not convenient - `is_signed` has to be used and representation of signed numbers has to be assumed. Floating-point numbers are complicated too. * `std::formatted_size("{}", val)` could be used, but it is not available at compile time and generally seems like an overkill for getting the result. # Proposed API I propose API similar to the one from `std::to_chars()`. A constexpr function that instead of taking a value, takes the type as a template parameter. ```cpp // For integers constexpr std::size_t std::max_format_size<T>(int base = 10); // For floating-points constexpr std::size_t std::max_format_size<float/double/long double>(std::chars_format fmt); constexpr std::size_t std::max_format_size<float/double/long double>( std::chars_format fmt, int precision); ``` # Example usage Formatting an `int` value as hex characers. ```cpp int value = get_some_value(); constexpr std::size_t k_buf_size = std::max_format_size<int>(16); char buffer[k_buf_size + 1u]; // 1u for '\0' auto [ptr, _] = std::to_chars(buffer, buffer + k_buf_size, value, 16); *ptr = '\0'; std::cout << buffer; ``` # Where to put the functions The `<limits>` header seems like a good candidate. But, I think it should be available in `<charconv>`, as the functions are going to be used along with `std::to_chars()` very often. Best regards, Mateusz Janek
Received on 2021-03-20 06:27:03