[container] static_string ?
Beast has static_string which someone has asked to be move, is there any interest in moving this to Boost.Container? See: <https://github.com/boostorg/beast/issues/1691> <https://github.com/boostorg/beast/blob/b7230f12f16fe7a9f7a1ece5be1f607c8552448a/include/boost/beast/core/static_string.hpp> -- Regards, Vinnie Follow me on GitHub: https://github.com/vinniefalco
On Mon, Sep 9, 2019 at 9:59 AM Vinnie Falco via Boost <boost@lists.boost.org> wrote:
Beast has static_string which someone has asked to be move, is there any interest in moving this to Boost.Container?
See:
<https://github.com/boostorg/beast/issues/1691>
< https://github.com/boostorg/beast/blob/b7230f12f16fe7a9f7a1ece5be1f607c85524...
This is of course a question for Ion, but I would like to see this made more widely available. Zach
On Mon, Sep 9, 2019 at 11:23 AM Zach Laine <whatwasthataddress@gmail.com> wrote:
This is of course a question for Ion, but I would like to see this made more widely available.
Another entirely acceptable option (or even a preferred option for many I am sure) is to put it in its own repository as its own Boost library. It would have to go through the review process. As its own Boost library it would be quite modular, it should only need Boost.Assert, Boost.Config, and whatever provides BOOST_THROW_EXCEPTION. Is anyone interesting in going down this route? Thanks
On 09/09/2019 20:23, Zach Laine via Boost wrote:
On Mon, Sep 9, 2019 at 9:59 AM Vinnie Falco via Boost <boost@lists.boost.org> wrote:
Beast has static_string which someone has asked to be move, is there any interest in moving this to Boost.Container?
See:
<https://github.com/boostorg/beast/issues/1691>
< https://github.com/boostorg/beast/blob/b7230f12f16fe7a9f7a1ece5be1f607c85524...
This is of course a question for Ion, but I would like to see this made more widely available.
Hi, Sorry for the delay. I think it's a good idea, it seems a really useful container. To ease the maintenance, I think we should merge container::string and container::static_string implementations to reuse as much as code as we can. Best, Ion
On Mon, Sep 9, 2019 at 2:04 PM Ion Gaztañaga via Boost <boost@lists.boost.org> wrote:
...I think it's a good idea, it seems a really useful container. To ease the maintenance, I think we should merge container::string and container::static_string implementations to reuse as much as code as we can.
I've been discussing this on the C++ Slack and I think a separate Boost library would be best. There is a growing clamor from users for more modularity from Boost. Having more fine-grained libraries would help with this. There are other benefits to having a separate library: - Separate repository has its own Travis compilation / time limits - Comprehensive valgrind / sanitizer tests will take less time - The tests on CI will take less time to complete in general - Coverage reports would be more meaningful (since they include less code) A one-line change to, f.ex. Boost.FixedString (provisional name) would have a faster turn-around time on CI than a one-line change made to Boost.Container. Another point worth discussing, is overall compilation performance. Once of the complaints about Beast is the heavy reliance on templated algorithms. Some of these Beast algorithms simply cannot be changed since they operate on concepts. However we identified parts of Beast that could be made into normal functions, and there is a preprocessor macro to allow those function definitions to be compiled into their own library. For example: <https://github.com/boostorg/beast/blob/b7230f12f16fe7a9f7a1ece5be1f607c8552448a/include/boost/beast/http/basic_parser.hpp#L686> For static_string (alternatively named: fixed_string) it should be very practical to make most of the implementation consist only of ordinary (non-template) functions, at least for the most common template parameter of char_traits<char>. We could make the header-only compilation mode also available via macro as shown above. This will make static_string very lean in terms of compilation resources and increase the appeal of the library. Regards
Le lundi 09 septembre 2019 à 23:03 +0200, Ion Gaztañaga via Boost a écrit :
On 09/09/2019 20:23, Zach Laine via Boost wrote:
On Mon, Sep 9, 2019 at 9:59 AM Vinnie Falco via Boost < boost@lists.boost.org> wrote:
Beast has static_string which someone has asked to be move, is there any interest in moving this to Boost.Container?
See:
Sorry for the delay. I think it's a good idea, it seems a really useful container. To ease the maintenance, I think we should merge container::string and container::static_string implementations to reuse as much as code as we can.
As i recently had to write one, i raise another hand for a static_string in boost. One thing that was important for me was trivially_copyable property. It can be quite hard to achieve when sharing implementations (static vector, for example, lacks this property while it could offer it for trivial T). Regards, Julien
On 9. Sep 2019, at 23:03, Ion Gaztañaga via Boost <boost@lists.boost.org> wrote:
On 09/09/2019 20:23, Zach Laine via Boost wrote:
On Mon, Sep 9, 2019 at 9:59 AM Vinnie Falco via Boost <boost@lists.boost.org> wrote:
Beast has static_string which someone has asked to be move, is there any interest in moving this to Boost.Container?
See:
<https://github.com/boostorg/beast/issues/1691>
< https://github.com/boostorg/beast/blob/b7230f12f16fe7a9f7a1ece5be1f607c85524...
This is of course a question for Ion, but I would like to see this made more widely available.
Hi,
Sorry for the delay. I think it's a good idea, it seems a really useful container. To ease the maintenance, I think we should merge container::string and container::static_string implementations to reuse as much as code as we can.
This was probably discussed here before, but could someone remind me why static_string and static_vector need to exist as separate containers at all? Why don't we use a boost::vector and boost::string with a special allocator that offers a fixed-sized memory pool allocated from the stack?
"Hans Dembinski via Boost" <boost@lists.boost.org> – 10 septembre 2019 11:07
This was probably discussed here before, but could someone remind me why static_string and static_vector need to exist as separate containers at all? Why don't we use a boost::vector and boost::string with a special allocator that offers a fixed-sized memory pool allocated from the stack?
This is how static_vector is implemented, afaik. The main drawback is that it makes static_vector not trivially_copyable even for trivial T. I ended up reimplementing a custom static_vector for this reason only. I don't think it makes much sense to have a static_string which is not trivially copyable (which would probably be the case if using a specialization with an allocator). Regards, Julien
On 10. Sep 2019, at 12:19, julien.blanc@tgcm.eu wrote:
"Hans Dembinski via Boost" <boost@lists.boost.org> – 10 septembre 2019 11:07
This was probably discussed here before, but could someone remind me why static_string and static_vector need to exist as separate containers at all? Why don't we use a boost::vector and boost::string with a special allocator that offers a fixed-sized memory pool allocated from the stack?
This is how static_vector is implemented, afaik.
You are right, https://www.boost.org/doc/libs/1_71_0/doc/html/boost/container/static_vector... It would be nice if dtl::static_vector_allocator was part of the public interface. It seems that static_vector could just be an alias template in C++11.
The main drawback is that it makes static_vector not trivially_copyable even for trivial T. I ended up reimplementing a custom static_vector for this reason only.
I don't think it makes much sense to have a static_string which is not trivially copyable (which would probably be the case if using a specialization with an allocator).
That is an interesting point.
On 10/09/2019 12:40, Niall Douglas via Boost wrote:
On 09/09/2019 17:59, Vinnie Falco via Boost wrote:
Beast has static_string which someone has asked to be move, is there any interest in moving this to Boost.Container?
What's the advantage over a string_view?
To answer my own question, it's a mutable string_view. So long as it's not called static_string, because it's not, I'm for this. Incidentally, over at WG14 we were discussing a mutable string view object built into the C language. Ours is nothing like this, however. Niall
Von: "Niall Douglas via Boost" <boost@lists.boost.org> On 10/09/2019 12:40, Niall Douglas via Boost wrote:
On 09/09/2019 17:59, Vinnie Falco via Boost wrote:
Beast has static_string which someone has asked to be move, is there any interest in moving this to Boost.Container?
What's the advantage over a string_view?
To answer my own question, it's a mutable string_view.
I thought a static_string is a type that owns the string data, so nothing like a string_view (mutable or not) at all. The difference compared to a std::string would be the same as the difference between std::array vs std::vector i.e. the data is stored in a fixed buffer inside the type and not on the heap, which in turn means there is a fixed capacity (configurable via a template parameter). Thats exactly what I see in https://github.com/boostorg/beast/blob/b7230f12f16fe7a9f7a1ece5be1f607c85524... so I'm not sure, where your comparison to string_view comes from. Mike
Niall
On Tuesday, September 10, 2019, Mike wrote:
Von: "Niall Douglas via Boost" <boost@lists.boost.org> On 10/09/2019 12:40, Niall Douglas via Boost wrote:
On 09/09/2019 17:59, Vinnie Falco via Boost wrote:
Beast has static_string which someone has asked to be move, is there any interest in moving this to Boost.Container?
What's the advantage over a string_view?
To answer my own question, it's a mutable string_view.
I thought a static_string is a type that owns the string data, so nothing like a string_view (mutable or not) at all.
Correct. Glen
On 10/09/2019 13:32, Mike via Boost wrote:
Von: "Niall Douglas via Boost" <boost@lists.boost.org> On 10/09/2019 12:40, Niall Douglas via Boost wrote:
On 09/09/2019 17:59, Vinnie Falco via Boost wrote:
Beast has static_string which someone has asked to be move, is there any interest in moving this to Boost.Container?
What's the advantage over a string_view?
To answer my own question, it's a mutable string_view.
I thought a static_string is a type that owns the string data, so nothing like a string_view (mutable or not) at all.
The difference compared to a std::string would be the same as the difference between std::array vs std::vector i.e. the data is stored in a fixed buffer inside the type and not on the heap, which in turn means there is a fixed capacity (configurable via a template parameter).
Thats exactly what I see in https://github.com/boostorg/beast/blob/b7230f12f16fe7a9f7a1ece5be1f607c85524...
so I'm not sure, where your comparison to string_view comes from.
I don't care for the storage owning part at all. If you want that, use a custom allocator with std::string. Any time I've written this sort of thing, it's a mutable string view operating upon an externally managed char array. It has layout of: class mutable_string_view { char *_begin, *_end, *_capacity; }; This is trivially copyable. I usually use storage as: static std::atomic<char *> next_mutable_string; ... where the char * points into some buffer I've thrown at the problem. You atomically increment the atomic pointer by capacity, return a mutable string view. Niall
Vinnie Falco wrote:
Beast has static_string which someone has asked to be move, is there any interest in moving this to Boost.Container?
Having this outside Beast would certainly make it more discoverable! I have been making a lot of use of boost::container::small_vector and boost::container::static_vector recently. A first thought is that one could wrap those in a vector-to-string adaptor to get small and static strings (and I have a string_facade class template that does much of that). I think it would be useful to have a small_string implemented like this, but it's not the best solution for static_string. I note that the current Beast static_string stores a size_t and an array of chars. This is the right approach; it makes it trivially-copyable. But if small size is an aim (and I think it should be), we can do better; when N < 256, use a uint8_t for the size. In fact, use boost::integer::uint_t< log2<N> >::least and get an optimal type for the size. I have just been looking at an old FixedString class that I wrote a few years ago, which is very much like the Beast static_string. The only other feature I added was an on-overflow policy template parameter, allowing you to throw, assert, truncate or UB on overflow. I don't know if I ever really used that. Regards, Phil.
On Tue, Sep 10, 2019 at 6:15 AM Phil Endecott via Boost <boost@lists.boost.org> wrote:
I note that the current Beast static_string stores a size_t and an array of chars. This is the right approach; it makes it trivially-copyable. But if small size is an aim (and I think it should be), we can do better; when N < 256, use a uint8_t for the size. In fact, use boost::integer::uint_t< log2<N> >::least and get an optimal type for the size.
Optimizing for size is not something that I considered, but this would be possible as per your suggestion. However, I am interested in a different direction - I'd like to make as much of the implementation based on ordinary functions (i.e. non-template) as possible. I often hear complaints from people about the use of templates in Beast, and in Asio and Networking TS. While these remarks are often uninformed there are some legitimate concerns, primarily that compilation resources (both time and space) are increased. Some ideas include: * Remove the CharT and Traits template types, who uses these anyway? * Derive the fixed_string template (which provides the capacity) from a non-template base class with one pure virtual member, this member is provided by the derived class and returns the base pointer, size, and capacity, to permit the optimizations of small size. This of course adds a pointer (8 or 4 bytes) to the size... Thanks
The container is now called fixed_string and I have made a new repository for it: <https://github.com/vinniefalco/fixed_string> It can be used without Beast, only requiring a few utility headers from Boost such as config, assert, etc.. There are javadocs in the source code but I am still working on integrating docca (a tool which converts javadocs into Boost Quickbook output to produce a reference). The tests pass, and there is Travis integration. What now? Do we want to propose this for Boost? Thanks
On 11. Sep 2019, at 21:06, Vinnie Falco via Boost <boost@lists.boost.org> wrote:
The container is now called fixed_string and I have made a new repository for it:
IMHO, the name fixed_string is worse than static_string, and it is inconsistent with boost::static_vector.
On Thu, 12 Sep 2019 at 11:14, Hans Dembinski via Boost <boost@lists.boost.org> wrote:
On 11. Sep 2019, at 21:06, Vinnie Falco via Boost <boost@lists.boost.org> wrote:
The container is now called fixed_string and I have made a new repository for it:
IMHO, the name fixed_string is worse than static_string,
+1
and it is inconsistent with boost::static_vector.
Interestingly, it to be named fixed_capacity_vector, renamed in revision 2 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0843r2.html Best regards, -- Mateusz Loskot, http://mateusz.loskot.net
On Thu, Sep 12, 2019 at 11:18 AM Mateusz Loskot via Boost < boost@lists.boost.org> wrote:
On Thu, 12 Sep 2019 at 11:14, Hans Dembinski via Boost
and it is inconsistent with boost::static_vector.
Interestingly, it to be named fixed_capacity_vector, renamed in revision 2 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0843r2.html
Which is a much better name IMHO. Longer, sure, but now it's clear and unambiguous. --DD
On Thu, 12 Sep 2019 at 14:15, Vinnie Falco via Boost <boost@lists.boost.org> wrote:
On Thu, Sep 12, 2019 at 2:38 AM Dominique Devienne via Boost <boost@lists.boost.org> wrote:
Which is a much better name IMHO
The name is the least important thing right now it can always be changed...can we please focus on substantive issues?
Yes, we can, the class should be made constexpr. degski -- @realdegski https://brave.com/google-gdpr-workaround/ "We value your privacy, click here!" Sod off! - degski "Anyone who believes that exponential growth can go on forever in a finite world is either a madman or an economist" - Kenneth E. Boulding "Growth for the sake of growth is the ideology of the cancer cell" - Edward P. Abbey
Gesendet: Donnerstag, 12. September 2019 um 13:14 Uhr Von: "Vinnie Falco via Boost" <boost@lists.boost.org>
On Thu, Sep 12, 2019 at 2:38 AM Dominique Devienne via Boost <boost@lists.boost.org> wrote:
Which is a much better name IMHO
The name is the least important thing right now it can always be changed...can we please focus on substantive issues?
Not sure, if this counts as substantial, but aside from making the string constexpr as suggested by degski (probably only useful/possible in c++14), have you considered a) to make the string trivially copyable (simply copy the whole storage, not just the bytes actually containing the string). This might make things easier for the optimizer. b) to conditionally enable support for std::string_view in c++17 (implicit conversion to and explicit construction from string_view) Regarding the idea of making this less "templaty" - I don't think is important enough to introduce a virtual function It makes things for the optimizer just so much harder. - Given, that the full type has to be a template anyway, I'm very skeptical if any technique provides enough benefit in terms of compile times to warrant the additional overhead and maybe complexity that the necessary indirection would incur. - The Traits template parameter might be a valid candidate for removal. I certainly never needed it, but my guess is that removing it makes only sense, if you also only support plain char (i.e. no wchar or char32_t) as a character type. I like the to_fixed_string function btw. Best Mike
On Thu, Sep 12, 2019 at 6:19 AM Mike via Boost <boost@lists.boost.org> wrote:
Not sure, if this counts as substantial...
Yes it does, pretty much anything that is not simply cosmetic (i.e. naming) is substantial :)
a) to make the string trivially copyable (simply copy the whole storage, not just the bytes actually containing the string). This might make things easier for the optimizer.
The purpose of fixed_capacity_string (see what I did there? LOL) is to facilitate allocation-free string mutation when the algorithm can reasonably impose an upper limit on the size of the resulting string. For example, Beast imposes an generous upper limit on some of the elements which make up the HTTP header. This allows the parser to use a stack based string to perform calculations and avoid allocations. To answer your question, no I have not considered the trivially copyable attribute when I wrote the class. We can certainly make it trivially copyable. Or not. I don't have a preference either way because my code does not copy such strings, and I do not know what the resulting performance characteristics will be for the use-cases where copying is needed. I can say that my strings are on the order of kilobytes, e.g. 1KB, 2KB, 4KB size strings. Copying all of a 4KB string when only a few hundred bytes are used may not be ideal, but absent experimentation it is hard to say if the tradeoff is worth it.
b) to conditionally enable support for std::string_view in c++17 (implicit conversion to and explicit construction from string_view)
Yes that is something that needs to be done. Beast kind of has support for this library-wide: <https://github.com/boostorg/beast/blob/b7230f12f16fe7a9f7a1ece5be1f607c8552448a/include/boost/beast/core/string_type.hpp#L24> I removed this option when I copied fixed_string into its own repository, because it does not feel right that EVERY library which wants to traffick in string_view has to invent its own configuration for deciding whether to use boost::string_view, std::string_view, or both. I have plans for more new repositories which need string views and it would be nice to have a Boost-wide solution - I'm very open to suggestions here. We should also think about the error_code related types from Boost.System, and the containers in Boost.SmartPtr for this sort of treatment. In Beast I did this: <https://github.com/boostorg/beast/blob/b7230f12f16fe7a9f7a1ece5be1f607c8552448a/include/boost/beast/core/error.hpp#L21> In theory I could change these aliases to use their std equivalents, but Asio gets in the way here since currently it can only use types from Boost.System.
Regarding the idea of making this less "templaty"
- I don't think is important enough to introduce a virtual function It makes things for the optimizer just so much harder.
- Given, that the full type has to be a template anyway, I'm very skeptical if any technique provides enough benefit in terms of compile times to warrant the additional overhead and maybe complexity that the necessary indirection would incur.
It can be done without the indirection: class fixed_capacity_string_base { char* begin_; std::size_t capacity_; protected: std::size_t size_; fixed_capacity_string_base( char* begin, std::size_t size, std::size_t capacity); public: //... }; template<std::size_t Capacity> class fixed_capacity_string : public fixed_capacity_string_base { char buf_[Capacity + 1]; public: //... }; The problem of course is that on 64-bit architectures, sizeof(fixed_capacity_string_base)==24 which is quite a bit of overhead. Personally, I don't mind, because it does not affect my intended use-case as described above. This year we made sweeping changes to Beast to convert function templates into ordinary functions wherever possible. The HTTP parser was one of the big wins. The result was faster compilation and reduced resource requirements on Travis. For users to gain the benefit they need simply include this file <boost/beast/src.hpp> in one of their translation units: <https://github.com/boostorg/beast/blob/b7230f12f16fe7a9f7a1ece5be1f607c8552448a/include/boost/beast/src.hpp> As you can see there is quite a lot of function definition code that is spared from repeated compilation when using this separate compilation mode. I do believe that the benefit is worth it. One common perception that ordinary programmers have about Boost is that it is slow to compile on account of the heavy templating. While it is possible to mitigate a lot of this burden, it requires discipline and above-average skill at refactoring the physical structure of a program. Skills which are unfortunately in short supply. I think both the perception and performance of the Boost Library Collection is made more favorable by investing in merciless elimination of templates where possible, with attention paid to reducing the compilation burden There is a class of algorithms which operate on strings which require an intermediate string as a working area to calculate their result. By refactoring the fixed string implementation into a non-template base class, it becomes possible for these algorithms to be written as ordinary functions. Here is an example signature: string_view f (string_view input1, string_view input2, fixed_capacity_string_base& temp);
- The Traits template parameter might be a valid candidate for removal. I certainly never needed it, but my guess is that removing it makes only sense, if you also only support plain char (i.e. no wchar or char32_t) as a character type.
I can be perfectly happy supporting only `char`, but we could offer wchar and char32_t variants using explicit instantiation in the non-header-only configuration mode, and still get the benefits of separate compilation.
I like the to_fixed_string function btw.
Thanks! Composing integers as part of larger strings is a natural fit for fixed_capacity_string, e.g. "Content-Length: 2048\r\n" Regards
"Vinnie Falco via Boost" <boost@lists.boost.org> – 12 septembre 2019 16:06
On Thu, Sep 12, 2019 at 6:19 AM Mike via Boost <boost@lists.boost.org> wrote:
Not sure, if this counts as substantial...
Yes it does, pretty much anything that is not simply cosmetic (i.e. naming) is substantial :)
a) to make the string trivially copyable (simply copy the whole storage, not just the bytes actually containing the string). This might make things easier for the optimizer.
The purpose of fixed_capacity_string (see what I did there? LOL) is to facilitate allocation-free string mutation when the algorithm can reasonably impose an upper limit on the size of the resulting string. For example, Beast imposes an generous upper limit on some of the elements which make up the HTTP header. This allows the parser to use a stack based string to perform calculations and avoid allocations.
Why not use a static_vector<char> ? In my experiments replacing strings by vectors of chars has always been a good idea. There is a cost associated with maintaining the null termination of strings, and in some context it is measureable. Given that any modern non-owning interface should use string_view rather than a plain char const*, it seems that it is only when interoperating with C that such a class would be useful. Regards, Julien
On Fri, Sep 13, 2019 at 3:28 AM <julien.blanc@tgcm.eu> wrote:
Why not use a static_vector<char> ?
static_vector is missing all of the string-oriented algorithms.
There is a cost associated with maintaining the null termination of strings
Yeah, that's easily fixed. We can add the function fixed_capacity_string::c_str() which will put the terminator on and return a pointer, this way the mutating operations do not need to always leave the string in a null terminated state. Thanks
On 13/09/2019 14:43, Vinnie Falco via Boost wrote:
On Fri, Sep 13, 2019 at 3:28 AM <julien.blanc@tgcm.eu> wrote:
Why not use a static_vector<char> ?
static_vector is missing all of the string-oriented algorithms.
There is a cost associated with maintaining the null termination of strings
Yeah, that's easily fixed. We can add the function fixed_capacity_string::c_str() which will put the terminator on and return a pointer, this way the mutating operations do not need to always leave the string in a null terminated state.
But then c_str() would not be "const noexcept". Best, Ion
Is that a big deal? I dont think so ... On Fri, Sep 13, 2019, 3:58 PM Ion Gaztañaga via Boost <boost@lists.boost.org> wrote:
On 13/09/2019 14:43, Vinnie Falco via Boost wrote:
On Fri, Sep 13, 2019 at 3:28 AM <julien.blanc@tgcm.eu> wrote:
Why not use a static_vector<char> ?
static_vector is missing all of the string-oriented algorithms.
There is a cost associated with maintaining the null termination of strings
Yeah, that's easily fixed. We can add the function fixed_capacity_string::c_str() which will put the terminator on and return a pointer, this way the mutating operations do not need to always leave the string in a null terminated state.
But then c_str() would not be "const noexcept".
Best,
Ion
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
On 2019-09-14 02:19, Vinnie Falco via Boost wrote:
On Fri, Sep 13, 2019, 3:58 PM Ion Gaztañaga via Boost <boost@lists.boost.org> wrote:
On 13/09/2019 14:43, Vinnie Falco via Boost wrote:
On Fri, Sep 13, 2019 at 3:28 AM <julien.blanc@tgcm.eu> wrote:
Why not use a static_vector<char> ?
static_vector is missing all of the string-oriented algorithms.
There is a cost associated with maintaining the null termination of strings
Yeah, that's easily fixed. We can add the function fixed_capacity_string::c_str() which will put the terminator on and return a pointer, this way the mutating operations do not need to always leave the string in a null terminated state.
But then c_str() would not be "const noexcept".
Is that a big deal? I dont think so ...
It is. Obtaining C-style string without exceptions is important e.g. in exception::what(). It is also not uncommon to want to process strings in a non-throwing fashion involving C standard library, and it requires null-terminated strings. Also note that c_str() is an observer, which is supposed to not modify the string (IOW must be callable on a const string). In general, I see throwing and mutating c_str() as a major hinderance. C-style strings are still wide-spead, regardless of how much we love string_view.
On Sat, Sep 14, 2019 at 3:16 AM Andrey Semashev via Boost < boost@lists.boost.org> wrote:
On 2019-09-14 02:19, Vinnie Falco via Boost wrote:
On Fri, Sep 13, 2019, 3:58 PM Ion Gaztañaga via Boost <
boost@lists.boost.org>
wrote:
On 13/09/2019 14:43, Vinnie Falco via Boost wrote:
On Fri, Sep 13, 2019 at 3:28 AM <julien.blanc@tgcm.eu> wrote:
Why not use a static_vector<char> ?
static_vector is missing all of the string-oriented algorithms.
There is a cost associated with maintaining the null termination of strings
Yeah, that's easily fixed. We can add the function fixed_capacity_string::c_str() which will put the terminator on and return a pointer, this way the mutating operations do not need to always leave the string in a null terminated state.
But then c_str() would not be "const noexcept".
Is that a big deal? I dont think so ...
It is. Obtaining C-style string without exceptions is important e.g. in exception::what(). It is also not uncommon to want to process strings in a non-throwing fashion involving C standard library, and it requires null-terminated strings. Also note that c_str() is an observer, which is supposed to not modify the string (IOW must be callable on a const string). In general, I see throwing and mutating c_str() as a major hinderance. C-style strings are still wide-spead, regardless of how much we love string_view.
Perhaps we could do as Vinnie said, but just name the function as `terminate()` instead of `c_str()`.
On Sat, Sep 14, 2019 at 2:21 PM Roberto Hinz via Boost <boost@lists.boost.org> wrote:
Perhaps we could do as Vinnie said, but just name the function as `terminate()` instead of `c_str()`.
Would this be OK? template <std::size_t N> class static_string { mutable char buf_[N+1]; public: ... char const* c_str() const noexcept { buf_[size()] = '\0'; return buf_; } }; Or we could just leave it the way that it is, and pay for keeping the string null terminated at all times, that's not so bad really. Regards
On Sat, Sep 14, 2019 at 7:13 PM Vinnie Falco <vinnie.falco@gmail.com> wrote:
On Sat, Sep 14, 2019 at 2:21 PM Roberto Hinz via Boost <boost@lists.boost.org> wrote:
Perhaps we could do as Vinnie said, but just name the function as `terminate()` instead of `c_str()`.
Would this be OK?
template <std::size_t N> class static_string { mutable char buf_[N+1]; public: ... char const* c_str() const noexcept { buf_[size()] = '\0'; return buf_; } };
This is OK to me.
On 2019-09-15 01:13, Vinnie Falco via Boost wrote:
Would this be OK?
template <std::size_t N> class static_string { mutable char buf_[N+1]; public: ... char const* c_str() const noexcept { buf_[size()] = '\0'; return buf_; } };
No, this won't work with const storage. You won't be able to use it in non-writable memory and such strings won't be placed in const sections of the executable and therefore won't be shared between processes.
Or we could just leave it the way that it is, and pay for keeping the string null terminated at all times, that's not so bad really.
Yes, since you have the buffer size for the terminating zero anyway, maintaining the terminating zero on string modification is the way to go.
Small update: The repository is here: <https://github.com/vinniefalco/fixed_string> It builds across a range of C++11 conforming toolchains. I am still going through function by function adding javadocs and ensuring that the interface matches the current (C++20) specification of std::string. Feel free to open new issues or comment on existing issues Regards
I don't see a real need for the base class. On Thu, Sep 12, 2019 at 11:05 AM Vinnie Falco via Boost < boost@lists.boost.org> wrote:
Here is an example signature:
string_view f (string_view input1, string_view input2, fixed_capacity_string_base& temp);
I would rather use span<char> or span<char, N> in this case.
- The Traits template parameter might be a valid candidate for
removal. I certainly never needed it, but my guess is that removing it makes only sense, if you also only support plain char (i.e. no wchar or char32_t) as a character type.
I can be perfectly happy supporting only `char`, but we could offer wchar and char32_t variants using explicit instantiation in the non-header-only configuration mode, and still get the benefits of separate compilation.
I like the ideia of removing Traits, but I would keep CharT. Don't see any inconsistency in that. Regards
On Sat, Sep 14, 2019 at 9:15 AM Roberto Hinz <robhz786@gmail.com> wrote:
string_view f (string_view input1, string_view input2, fixed_capacity_string_base& temp);
... I would rather use span<char> or span<char, N> in this case.
`span` doesn't have any useful member function algorithms for operating on strings like inserting a substring at a given location.
On Sat, Sep 14, 2019 at 3:35 PM Vinnie Falco <vinnie.falco@gmail.com> wrote:
On Sat, Sep 14, 2019 at 9:15 AM Roberto Hinz <robhz786@gmail.com> wrote:
string_view f (string_view input1, string_view input2, fixed_capacity_string_base& temp);
... I would rather use span<char> or span<char, N> in this case.
`span` doesn't have any useful member function algorithms for operating on strings like inserting a substring at a given location.
Maybe we could create a new class `string_slice` that references a mutable array of chars
On Sat, Sep 14, 2019 at 11:46 AM Roberto Hinz <robhz786@gmail.com> wrote:
Maybe we could create a new class `string_slice` that references a mutable array of chars
Well, yes, that's exactly the point of the base class! The algorithms are expressed in terms of non-template member functions. Regards
On Sat, Sep 14, 2019 at 4:46 PM Vinnie Falco <vinnie.falco@gmail.com> wrote:
On Sat, Sep 14, 2019 at 11:46 AM Roberto Hinz <robhz786@gmail.com> wrote:
Maybe we could create a new class `string_slice` that references a mutable array of chars
Well, yes, that's exactly the point of the base class! The algorithms are expressed in terms of non-template member functions.
Regards
But a base class could bring downsides to fixed_capacity_string, like increasing its size. I would prefer is a class that is convertible from fixed_capacity_string. Regards
On 9/12/19 3:19 PM, Mike via Boost wrote:
b) to conditionally enable support for std::string_view in c++17 (implicit conversion to and explicit construction from string_view)
For the string_view to bikeshedding_string conversion I would prefer a temmplated constructor that takes a container (a Range concept to be precise.) That way it works with any type that has begin() and end(), and we do not create a dependency on std::string_view. The container could be further constrained to those with value_type == char.
On Thu, Sep 12, 2019 at 4:29 PM Bjorn Reese via Boost <boost@lists.boost.org> wrote:
On 9/12/19 3:19 PM, Mike via Boost wrote:
b) to conditionally enable support for std::string_view in c++17 (implicit conversion to and explicit construction from string_view)
For the string_view to bikeshedding_string conversion I would prefer a temmplated constructor that takes a container (a Range concept to be precise.) That way it works with any type that has begin() and end(), and we do not create a dependency on std::string_view. The container could be further constrained to those with value_type == char.
That's fine from std::string_view to fixed_capacity_string. But the reverse would be awkward, and not an implicit conversion to std::string_view, no? --DD
On Thu, Sep 12, 2019 at 10:56 AM Dominique Devienne via Boost < boost@lists.boost.org> wrote:
On Thu, Sep 12, 2019 at 4:29 PM Bjorn Reese via Boost < boost@lists.boost.org> wrote:
On 9/12/19 3:19 PM, Mike via Boost wrote:
b) to conditionally enable support for std::string_view in c++17 (implicit conversion to and explicit construction from string_view)
For the string_view to bikeshedding_string conversion I would prefer a temmplated constructor that takes a container (a Range concept to be precise.) That way it works with any type that has begin() and end(), and we do not create a dependency on std::string_view. The container could be further constrained to those with value_type == char.
That's fine from std::string_view to fixed_capacity_string. But the reverse would be awkward, and not an implicit conversion to std::string_view, no? --DD
There are papers describing how the standard wants (is going) to do this, for both span and string_view: https://wg21.link/p1391 | https://wg21.link/p1394 Containers like bikeshedding_string were almost going to have implicit constructors from any range, but the paper was shot down and the new direction is using an explicit free function (https://wg21.link/p1206). This avoids shenanigans with overload resolution. But, since this is bikeshedding_string we may not need to worry about e.g. Allocator, and thusly the set of overloads will not be all of those in something like std::vector, but a much smaller set that can tolerate a templated range constructor on bikeshedding_string. Sincerely, JeanHeyd
On 9/12/19 5:11 PM, JeanHeyd Meneide via Boost wrote:
Containers like bikeshedding_string were almost going to have implicit constructors from any range, but the paper was shot down and the new direction is using an explicit free function (https://wg21.link/p1206).
I have been using this approach [1] for years, but found it inconvenient to use in practice because you have to specify the target type, which may have a long qualified name. Fortunately CTAD enables us to omit template argument types. [1] https://github.com/breese/trial.protocol/blob/develop/include/trial/dynamic/...
I have collected the feedback into individual issues for discussion and to track the progress of changes: On Thu, Sep 12, 2019 at 2:38 AM Dominique Devienne via Boost <boost@lists.boost.org> wrote:
Interestingly, it to be named fixed_capacity_vector, renamed in revision 2 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0843r2.html
Which is a much better name IMHO. Longer, sure, but now it's clear and unambiguous. --DD
https://github.com/vinniefalco/fixed_string/issues/1 On Thu, Sep 12, 2019 at 4:29 AM degski via Boost <boost@lists.boost.org> wrote:
...the class should be made constexpr.
https://github.com/vinniefalco/fixed_string/issues/2 On Thu, Sep 12, 2019 at 6:19 AM Mike via Boost <boost@lists.boost.org> wrote:
...make the string trivially copyable (simply copy the whole storage, not just the bytes actually containing the string).
https://github.com/vinniefalco/fixed_string/issues/3 On Thu, Sep 12, 2019 at 6:19 AM Mike via Boost <boost@lists.boost.org> wrote:
...conditionally enable support for std::string_view in c++17 (implicit conversion to and explicit construction from string_view)
https://github.com/vinniefalco/fixed_string/issues/5 https://github.com/vinniefalco/fixed_string/issues/7 On Thu, Sep 12, 2019 at 7:29 AM Bjorn Reese via Boost <boost@lists.boost.org> wrote:
For the string_view to bikeshedding_string conversion I would prefer a temmplated constructor that takes a container (a Range concept to be precise.)
https://github.com/vinniefalco/fixed_string/issues/6 On Tue, Sep 10, 2019 at 6:15 AM Phil Endecott via Boost <boost@lists.boost.org> wrote:
...if small size is an aim (and I think it should be), we can do better; when N < 256, use a uint8_t for the size. In fact, use boost::integer::uint_t< log2<N> >::least and get an optimal type for the size.
https://github.com/vinniefalco/fixed_string/issues/8 Feel free to add to these issues or to create new ones (or discuss on the list) Thanks
On 12. Sep 2019, at 13:14, Vinnie Falco via Boost <boost@lists.boost.org> wrote:
On Thu, Sep 12, 2019 at 2:38 AM Dominique Devienne via Boost <boost@lists.boost.org> wrote:
Which is a much better name IMHO
The name is the least important thing right now it can always be changed...can we please focus on substantive issues?
Consistency within boost is important. Names are important, because you are stuck with them forever. fixed_capacity_string is a good name. Thanks for listening.
On Thu, 12 Sep 2019 at 22:18, Hans Dembinski via Boost < boost@lists.boost.org> wrote:
fixed_capacity_string is a good name. Thanks for listening.
The std is (appears to be) going towards std::static_vector https://github.com/gnzlbg/static_vector#revision-2 . It is to be expected that std::static_vector will be followed by std::static_string. Consistency with the standard seems important (to me). I'm with Jagger and Richards here, let's paint the shed black. degski -- @realdegski https://brave.com/google-gdpr-workaround/ "We value your privacy, click here!" Sod off! - degski "Anyone who believes that exponential growth can go on forever in a finite world is either a madman or an economist" - Kenneth E. Boulding "Growth for the sake of growth is the ideology of the cancer cell" - Edward P. Abbey
Hi all, I have taken over development of Boost.FixedString, and have submitted it for review. Please, leave any feedback you have. Applicable links: Github: https://github.com/18 Repo: https://github.com/18/fixed_string Docs: https://18.github.io/doc/fixed_string -- Sent from: http://boost.2283326.n4.nabble.com/Boost-Dev-f2600599.html
On Fri, Nov 8, 2019 at 4:16 PM sdkrystian via Boost <boost@lists.boost.org> wrote:
I have taken over development of Boost.FixedString, and have submitted it for review. Please, leave any feedback you have.
Wonderful, thank you Krystian for doing this work. I believe this project is ready for a review manager? Thanks
On Mon, Sep 9, 2019 at 9:59 AM Vinnie Falco <vinnie.falco@gmail.com> wrote:
...static_string...
I would like feedback on the possibility of removing the Traits template parameter. It seems rather pointless, and C++11 char_traits is not constexpr. We could probably cobble a way to support a non-constexpr char_traits for all but char and wchar_t, but I think it would be better not to have it at all because really, who uses char traits? It is an extra compilation burden with no benefit. Thanks
On Sun, Oct 13, 2019 at 5:59 PM Vinnie Falco via Boost <boost@lists.boost.org> wrote:
On Mon, Sep 9, 2019 at 9:59 AM Vinnie Falco <vinnie.falco@gmail.com> wrote:
...static_string...
I would like feedback on the possibility of removing the Traits template parameter. It seems rather pointless, and C++11 char_traits is not constexpr. We could probably cobble a way to support a non-constexpr char_traits for all but char and wchar_t, but I think it would be better not to have it at all because really, who uses char traits? It is an extra compilation burden with no benefit.
Unless you want to reimplement C string functions, you will need an equivalent of char_traits. And I really hope you don't reimplement C functions, because they would be most likely less optimized.
participants (19)
-
Andrey Semashev
-
Bjorn Reese
-
degski
-
Dominique Devienne
-
Gavin Lambert
-
Glen Fernandes
-
Hans Dembinski
-
Ion Gaztañaga
-
JeanHeyd Meneide
-
Julien Blanc
-
julien.blanc@tgcm.eu
-
Mateusz Loskot
-
Mike
-
Niall Douglas
-
Phil Endecott
-
Roberto Hinz
-
sdkrystian
-
Vinnie Falco
-
Zach Laine