[review][fixed_string] FixedString review starts today
The Boost formal review of Krystian Stasiowski and Vinnie Falco's FixedString library starts today November 25 and extends up to December 4. Description FixedString provides a dynamically resizable string of characters with compile-time fixed capacity and contiguous embedded storage in which the characters are placed within the string object itself. Its API closely resembles that of std::string. Repo and docs GitHub repository: https://github.com/18/fixed_string Online docs: https://18.github.io/doc/fixed_string Review questions Here are some questions you might want to answer in your review: - What is your evaluation of the design? - What is your evaluation of the implementation? - What is your evaluation of the documentation? - What is your evaluation of the potential usefulness of the library? - Did you try to use the library? With what compiler? Did you have any problems? - How much effort did you put into your evaluation? A glance? A quick reading? In-depth study? - Are you knowledgeable about the problem domain? And finally, every review should answer this question: - Do you think the library should be accepted as a Boost library? I invite you to submit your review, either publicly to the developers or the users lists, or else, if for whatever reason you don't want to go public, directly to me. Thank you for investing your time on reviewing Krystian and Vinnie's work and for contributing to the advancement of Boost. Best regards, Joaquín M López Muñoz Review manager for candidate Boost.FixedString
On Sun, Nov 24, 2019 at 5:00 PM Joaquin M López Muñoz via Boost-users < boost-users@lists.boost.org> wrote:
The Boost formal review of Krystian Stasiowski and Vinnie Falco's FixedString library starts today November 25 and extends up to December 4.
[snip]
Review questions
Here are some questions you might want to answer in your review: - What is your evaluation of the design?
A drop-in replacement for std::string should not add elements to the design (string_view_type, return type of substr(), etc.), as users will come to depend upon them, and then if they want to switch back to std::string, their code will not compile. I personally do not care about the drop-in replacement goal, but adding things to the design not present in std::string subverts that somewhat. Throwing when the capacity would be exceeded is wrong. The distinction between a failure mode that should throw and one that should assert/invoke UB is that the exception allows the user to recover, and the assert simply informs the user that their code is broken. Since the capacity is known statically, and since there is no way to change it at runtime, reporting this as a recoverable error, rather than a programmer error, is inappropriate. I know this is at odds with the drop-in replacement goal, but using a type that has at most N characters of stack in place of a type that can use nearly all available heap will never truly be a drop-in replacement. Besides, that ship sailed when you changed the return type of substr(). Could you explain why the fixed_string API is not constexpr? Is it for C++11 compatability? Could you also explain how this meets the constexpr use case goal? Would it be unreasonable to add op+ back in for operands of the same type? There's no difficulty determining the size of fixed_string<8>("foo") + fixed_string<8>("bar"), right? That's no different from fixed_string<8>("foo") + "bar", which *is* supported. If capacity() were constexpr static, you would not need static_capacity. I prefer the name "static_string", in keeping with the long-established "static_vector" from Boost.Container. to_fixed_string() takes any integral type. This is wrong. Here are the overloads for to_string() from the standard: string to_string(int val); string to_string(unsigned val); string to_string(long val); string to_string(unsigned long val); string to_string(long long val); string to_string(unsigned long long val); string to_string(float val); string to_string(double val); string to_string(long double val); Note the presence of to_string() overloads for float, double, and long double. Note the conspicuous absence of overloads for char, char8_t, char16_t, and char32_t. This is intentional, and to_fixed_string() should follow this. It's fine to use the current implementation of to_fixed_string() as a common implementation for the integral overloads above, but you should not accept the character types, and should accept the floating point types above. - What is your evaluation of the implementation?
Please consider adding BOOST_ASSERTs of preconditions. For instance,
back() may access a character at an index >= size(), but < capacity().
This will never be caught by ASan or Valgrind, and will not segfault,
because a random char within an array of char is always ok to read, within
the lifetime of the array. An assert will let users find those errors
*much* more easily.
Will the optional dependency on Boost become a permanent dependency on
Boost if the library is accepted? BOOST_FIXED_STRING_ASSERT() and friends
are confusing to those familiar with Boost implementations.
to_fixed_string() has a constrained declaration, and static_asserts that
the constraint is satisfied inside the body. It seems that the
static_assert is just noise.
This appears quite wrong, even if Augustin is the one behind it. Did he
say why he expects that to work? It looks like it accepts doubles as
iterators, for instance.
// Because k-ballo said so
template<class T>
using is_input_iterator =
std::integral_constant
- What is your evaluation of the documentation?
Motivation: "A dynamically-resizable string is required within constexpr functions." -> "A dynamically-resizable string is required within constexpr functions (before C++20)." (since std::string is usable in a constexpr context in C+20 and later). Iterators: You forgot to note that increasing the length of the string will never invalidate iterators, since those operations never change the capacity. All of the links to source code in the synopses give me 404s. I feel like the documentation that exists, but defines exactly the same functionality as std::string (e.g. erase()), should be documented via reference to std::string. The fact that all these APIs exist within the fixed_string docs means I cannot easily find the variations from std::string. For instance, I know that any allocating function must throw if the capacity is exceeded (from the intro), but I don't know if there are other variations I need to know about without reading the API docs. With no indication where those variations might exist, I end up needing to read all the API descriptions, most of them identical to what I already know std::string to do, in order to find them. Please short-circuit this for me by only supplying the varying API docs, and saying "the rest is what std::string does, except that the capacity is fixed at N". Of course, if you change throws to asserts in the ways I suggested above, you'll need to note that as well. If you're going to replicate all the API docs from std::string, please don't leave out the type constraint documentation. For instance, fixed_string(T const& t, size_type pos, size_type n); has a constraint on "T" that you do not document. You may want to briefly state why it is insufficient just to use a std::string with a fixed-capacity allocator. I did not initially look a the definition of iterator and const_iterator, but once I did I was happy to see that they were both plain pointers. It's really useful to know that the iterator type is guaranteed to be a pointer, and calling that out explicitly would help users. - What is your evaluation of the potential usefulness of the library?
Very, based on the usefulness of boost::container::static_vector in contexts in which the maximum number of elements is known.
- Did you try to use the library? With what compiler? Did you have any problems?
I did not try to use it, simply because I know how std::string works. :)
- How much effort did you put into your evaluation? A glance? A quick reading? In-depth study?
I spent about 3 hours reading the documentation and implementation.
- Are you knowledgeable about the problem domain?
Yes. In particular, I have implemented multiple string-like types.
And finally, every review should answer this question: - Do you think the library should be accepted as a Boost library?
Yes, with these conditions: - the to_fixed_string() overloads are changed to match the std::to_string() overloads; - that detail::is_input_iterator is explained or fixed; and - compile-fail tests are added to verify that those functions with constraints are correctly constrained. Zach
...
There seems to be a lot of disagreement on handling overflow so I'd like to remind everyone of why this library is being proposed: A Beast user asked "Why isn't beast::static_string in a separate Boost library? It is quite useful on its own." They did not ask to have the treatment of overflow changed, to have the sizeof the class optimized for various N, or to have any of the API changed at all. Make of this what you will. Regards
-----Original Message----- From: Boost-users
On Behalf Of Joaquin M López Muñoz via Boost-users Sent: 24 November 2019 23:00 To: boost@lists.boost.org; boost-users@lists.boost.org; boost- announce@lists.boost.org Cc: Joaquin M López Muñoz Subject: [Boost-users] [review][fixed_string] FixedString review starts today The Boost formal review of Krystian Stasiowski and Vinnie Falco's FixedString library starts today November 25 and extends up to December 4.
Description
FixedString provides a dynamically resizable string of characters with compile-time fixed capacity and contiguous embedded storage in which the characters are placed within the string object itself. Its API closely resembles that of std::string.
Repo and docs
GitHub repository: https://github.com/18/fixed_string Online docs: https://18.github.io/doc/fixed_string
Review questions
Here are some questions you might want to answer in your review: - What is your evaluation of the design?
Carefully considered.
- What is your evaluation of the implementation?
The adjective drop-in might mislead? There was much discussion of name; I agree that the name fixed_string is *very* misleading. I'd much prefer a longer name that mentions *capacity*. To throw my hat into the bike-shedding arena, can I propose "bounded_capacity_string" or even just "bounded_string". I put a higher value on constexpr than compatibility with older C++std versions. If that means that it doesn't work for pre-C++20, too bad.
- What is your evaluation of the documentation?
OK, but lacking examples and tutorials sections, and badly lacking a TOC (but bonus marks for an index), or links to sections and to the index. Loads of scrolling needed!
- What is your evaluation of the potential usefulness of the library?
Valuable.
- Did you try to use the library? With what compiler? Did you have any problems?
Perfunctory use. No problems.
- How much effort did you put into your evaluation? A glance? A quick reading? In- depth study?
Quick reading and followed the civilized discussions.
- Are you knowledgeable about the problem domain?
Not specially. The Big Thing that I know that arrays without sizes and null-terminated strings are the worse collision of two computer design disasters ! This is further proof, if one needed it.
And finally, every review should answer this question: - Do you think the library should be accepted as a Boost library?
Although there are some details and wrinkles to iron out, I'd like to see it in Boost to get wider use in anger, so Yes accept. Paul A. Bristow
participants (4)
-
Joaquin M López Muñoz
-
pbristow@hetp.u-net.com
-
Vinnie Falco
-
Zach Laine