template <typename CharT, typename Traits, typename Allocator, size_t SmallSize = /* implementation defiend*/> class basic_string;template <typename T, typename Allocator, size_t SmallSize = 0> class vector;template <typename CharT, typename Traits, typename Allocator, size_t SmallSize = /* implementation defiend*/> class basic_string;
The small object optimization is also very useful for vector.
On Tuesday 03 March 2015 20:00:15 Matthew Fioravante wrote:
> Modern implementations are encouraged to implement the small string
> optimization (with implementation defined size) for std::string, reasoning
> that most strings tend to be small. While this may work very well in the
> general case, it can be either inadequate or a pessimization in other cases.
Since std::foo<N> is a different type from std::foo<M> where N != M, I don't
see the point in attempting to keep compatibility with the current
basic_string. Instead, be explicit that this is a different type and define the
SmallSize default value to be sizeof(std::basic_string<CharT>).
struct ChessPosition {
std::small_vector<ChessPiece,32> pieces;
};--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
El 04/03/2015 12:31, "David Rodríguez Ibeas" <dib...@ieee.org> escribió:
>
> I think that your problem is/should be addressed in a different direction, having an array_view/vector_view (I have heard about those in the past, I don't know if there has been any actual proposal, but it would be a simplified string_view). The 'ChessPosition' class looks like it should be an 'std::array', and if interfaces that only act on the data are implemented in terms of a *_view, then it should work just fine.
>
> In current C++, and if you need a dynamic size (i.e. std::array does not solve your problem), you can use an allocator to control where the memory comes from and make it local, you would still be paying for the additional bookkeeping inside vector, but if you need it to actually work that is available today...
I had the same thought. Why an allocator having an initial pre-allocated buffer of user-specified length and then use basic_string with that allocator wouldn't be an equivalent currently conformant solution?
> - Identifiers such a stock tickers which have a fixed upper bound on length.
If the fixed upper bound is small enough, you want to have a non-dynamic
version only. SSO isn't that. You want a real "small string".
I think that your problem is/should be addressed in a different direction, having an array_view/vector_view (I have heard about those in the past, I don't know if there has been any actual proposal, but it would be a simplified string_view). The 'ChessPosition' class looks like it should be an 'std::array', and if interfaces that only act on the data are implemented in terms of a *_view, then it should work just fine.
I had the same thought. Why an allocator having an initial pre-allocated buffer of user-specified length and then use basic_string with that allocator wouldn't be an equivalent currently conformant solution?
On Tuesday 03 March 2015 23:42:49 Arthur O'Dwyer wrote:
> In my opinion, "small_vector" would be a great addition to the standard
> library, but *only* if small_vector<T,N>& and vector<T>& are
> inter-convertible (in constant time). I believe that's doable, although I'm
> not sure how to write the *implementation* in purely standard-conforming
> C++ — it might require some reinterpret_casts.
You can't create a copy in constant time
> The use-case would be things like
>
> struct ChessPosition {
> std::small_vector<ChessPiece,32> pieces;
> };
>
> where ChessPosition's copy constructor and destructor get called *very*
> often, so copying the members needs to be *very* fast. Inlining the data
> (so no heap allocation needs to happen) is a big win.
True, but this is still O(n).
> We'd like to be able to tune the N parameter — for example, if we use
> small_vector<ChessPiece,16>, then early-game positions with more than 16
> pieces will require a heap allocation (relatively slower), but *every*
> position will take half the RAM (shrinking our memory footprint and the
> expense of copy-constructing these things).
El 04/03/2015 12:31, "David Rodríguez Ibeas" <dib...@ieee.org> escribió:
>
> I think that your problem is/should be addressed in a different direction, having an array_view/vector_view (I have heard about those in the past, I don't know if there has been any actual proposal, but it would be a simplified string_view). The 'ChessPosition' class looks like it should be an 'std::array', and if interfaces that only act on the data are implemented in terms of a *_view, then it should work just fine.
> In current C++, and if you need a dynamic size (i.e. std::array does not solve your problem), you can use an allocator to control where the memory comes from and make it local, you would still be paying for the additional bookkeeping inside vector, but if you need it to actually work that is available today...
On Tue, Mar 3, 2015 at 11:58 PM, Thiago Macieira <thi...@macieira.org> wrote:On Tuesday 03 March 2015 23:42:49 Arthur O'Dwyer wrote:
> In my opinion, "small_vector" would be a great addition to the standard
> library, but *only* if small_vector<T,N>& and vector<T>& are
> inter-convertible (in constant time). I believe that's doable, although I'm
> not sure how to write the *implementation* in purely standard-conforming
> C++ — it might require some reinterpret_casts.
You can't create a copy in constant timeI didn't say you should be able to create copies in constant time; I said that small_vector<T,N>& should be convertible to vector<T>& and vice versa.void generic_func(const std::vector<ChessPiece>& pieces) { ... }std::small_vector<ChessPiece, 16> mypieces;generic_func(mypieces);std::small_vector<ChessPiece, 18> hispieces;generic_func(hispieces);
There's no (semantic) reason this code shouldn't work, since vector and small_vector have exactly the same API. We shouldn't need to make generic_func a template just to get this to work, and we should even be able to do it without virtuals.
- Since we know the size and capacity of the vector, we can even push_back, up to a point...- ...and if we need to reallocate the data, then we have to be conservative and put it on the heap.Matthew Fioravante wrote:> For example the SSO buffer and the capacity can share space using a union since whenever> the SSO buffer is used, we implicitly know the capacity and don't need to store itI agree that this would be a useful goal, but I'm pretty sure it conflicts with my own pet goal to make std::small_vector<T,M>& interconvertible with std::small_vector<T,N>&, so you get to pick one or the other but not both. In my current design (which is not fully implemented) every kind of small_vector needs to know its "real" capacity; it can't trust its template parameter to reflect reality.
On Wed, Mar 4, 2015 at 7:39 AM, dgutson . <daniel...@gmail.com> wrote:
El 04/03/2015 12:31, "David Rodríguez Ibeas" <dib...@ieee.org> escribió:Right; bounded_vector is exactly a vector_view onto an array. (Except for the sad fact that SGI STL's vector_view doesn't track "capacity", and so will buffer-overflow if you push too many things onto it, if I read the code correctly. But that would be fixable.)
Notice that SGI vector_view isn't exactly analogous to string_view, because string_view is immutable whereas vector_view allows you to modify elements, push, pop, and resize (but not reserve, because the vector_view doesn't know how to allocate memory).
Oh, totally! All these things are "available today", if your definition of "available today" is "you have to write it yourself from scratch." :D
Also, unless I'm mistaken, C++14's std::vector doesn't make any guarantees about how much memory it's going to "allocate" via its allocator. In order for an allocator-based solution to work, we need a strong guarantee that std::vector<T>().resize(n) will make exactly one allocation of size n*sizeof(T). This is a good idea and must be coming soon anyway, but technically at the present moment there's no such guarantee, is there? /pedantry
On Wed, Mar 4, 2015 at 2:24 PM Arthur O'Dwyer <arthur....@gmail.com> wrote:On Wed, Mar 4, 2015 at 7:39 AM, dgutson . <daniel...@gmail.com> wrote:El 04/03/2015 12:31, "David Rodríguez Ibeas" <dib...@ieee.org> escribió:Right; bounded_vector is exactly a vector_view onto an array. (Except for the sad fact that SGI STL's vector_view doesn't track "capacity", and so will buffer-overflow if you push too many things onto it, if I read the code correctly. But that would be fixable.)
I did not mean to have an interface that allows insertion, only a *view* (you can transverse the existing elements but not add/remove). This might not apply to your particular problem, but it is a simple way of representing a sequence of contiguous elements.
Also, I am not even sure that you will get a huge advantage from using a local array versus dynamically allocated memory (the cost of allocation is becoming smaller and smaller), so using a plain std::vector with tcmalloc might give you most of the performance in most of the cases, but you should really measure.
O(1) time is still unachievable. The best you can hope for is
amortised constant time.