How to use std :: scoped_allocator_adapter?

As I understand it, std::scoped_allocator_adapter provides a control mechanism for specifying separately which distributor will be used by the container, its elements, elements of their elements, etc., assuming that the elements themselves are containers.

However, it is difficult for me to understand the semantics of std::scoped_allocator_adapter .

Bjarne Stroustrup provides the following 4 examples in the C ++ programming language, section 34.4.4, page 1001 (I will refer to them as example-1, example-2, etc. In my next questions):

We have four alternatives for placing row vectors:

 // vector and string use their own (the default) allocator: using svec0 = vector<string>; svec0 v0; // vector (only) uses My_alloc and string uses its own allocator (the default): using Svec1 = vector<string,My_alloc<string>>; Svec1 v1 {My_alloc<string>{my_arena1}}; // vector and string use My_alloc (as above): using Xstring = basic_string<char,char_traits<char>, My_alloc<char>>; using Svec2 = vector<Xstring,scoped_allocator_adaptor<My_alloc<Xstring>>>; Svec2 v2 {scoped_allocator_adaptor<My_alloc<Xstring>>{my_arena1}}; // vector uses its own alloctor (the default) and string uses My_alloc: using Xstring2 = basic_string<char, char_traits<char>, My_alloc<char>>; using Svec3 = vector<xstring2,scoped_allocator_adaptor<My_alloc<xstring>,My_alloc<char>>>; Svec3 v3 {scoped_allocator_adaptor<My_alloc<xstring2>,My_alloc<char>>{my_arena1}}; 

For completeness, My_alloc is defined in the book as follows:

 template<typename T> struct My_alloc { // use an Arena to allocate and deallocate bytes Arena& a; My_alloc(Arena& aa) : a(aa) { } My_alloc() {} // usual allocator stuff }; 

Now, to your questions:


Question-1: In example-3 elements of Svec2 use My_alloc<char>{my_arena1} to allocate memory for their elements (such as char )?


Question-2: If so, does this have anything to do with the fact that Xstring uses the custom distributor My_alloc<char> in its definition? IOW, even if Xstring were defined with a different distributor, I would not use Svec_2 elements yet My_alloc<char>{my_arena1} , since scoped_allocator_adaptor of Svec2_ dictates which distributor to use for distributions performed using Svec_2 and distributions performed by its elements (of type Xstring )?


Question-3: Consider the code below, which should be an option in Example-3. The v2_ elements (of type std::string in this case) use My_alloc<char>{my_arena1} ? If not, which distributor do they use?

 // both v2_ and its elements to use My_alloc<some_type>{my_arena1} using Svec2_ = vector<string, scoped_allocator_adaptor<My_alloc<string>>> // value_type std::string, instead of Xstring Svec2_ v2_ {scoped_allocator_adaptor<My_alloc<string>>{my_arena1}}; 

Question 4: Based on the explanation on www.cppreference.com below, it seems to me that in example 4 Svec3 does not use it by default strong> allocator std::allocator to allocate storage for its elements (such as Xstring2 ), but rather an "external allocator" which is equal to My_alloc<xstring> . Svec3 elements , on the other hand, will use MyAlloc<char> , which is the "internal distributor". (And not because it is the allocator specified in the Xstring2 definition, but because it is the "internal distributor" in scoped_allocator_adapter Svec3 .)

This is what he says at www.cppreference.com in the std::scoped_allocator_adaptor :

Considering:

 template< class OuterAlloc, class... InnerAlloc > class scoped_allocator_adaptor : public OuterAlloc; 

A container created directly using scoped_allocator_adaptor uses OuterAlloc to select its elements, but if the element itself is a container, it uses the internal allocator first . the elements of this container, if they themselves are containers, use a second internal distributor, etc. If there are more levels in the container than there are internal dispensers, the last distributor of the last internal is reused for all additional nested containers.

Based on this, should there be a correct example:

 // v3_ uses its default allocator(or rather std::allocator), while its elements use My_alloc using Xstring2 = basic_string<char, char_traits<char>, My_alloc<char>>; using Svec3_ = vector<Xstring2, scoped_allocator_adaptor<std::allocator<Xstring2>, My_alloc<char>>>; Svec3_ v3_ { scoped_allocator_adaptor<std::allocator<Xstring2>, My_alloc<char>>{my_arena1} }; 

So does this use of scoped_allocator_adaptor use the fact that Svec3_ distributions use std::allocator and its elements use My_alloc<char>{my_arena1} for their distributions?


I can say that I have fundamental misunderstandings of the distributed distributor model. Can someone point out what I'm missing?

+5
source share

Source: https://habr.com/ru/post/1264506/


All Articles