How to pass std :: vector with a custom allocator to a function that expects one using std :: allocator?

I work with an external library (pcl), so I need a solution that does not change existing function prototypes.

One function that I use generates std::vector<int, Eigen::aligned_allocator<int>> . The function I want to call next expects const boost::shared_ptr<std::vector<int, std::allocator<int>>> . I do not want to copy elements, because it is in the already slow critical part of my code. If not for dispenser mismatch, I would bypass the shared_ptr requirement by simply doing:

 // code that generates std::vector<int, Eigen::aligned_allocator<int>> source boost::shared_ptr<std::vector<int>> indices(new std::vector<int>); indices->swap(source); // use indices as intended 

This does not compile with the MSVC compiler because it cannot convert these two types of vectors. The only solution I've been thinking so far that is not copying the contents:

 // code that generates std::vector<int, Eigen::aligned_allocator<int>> source boost::shared_ptr<std::vector<int>> indices(new std::vector<int>); indices->swap(reinterpret_cast<std::vector<int>&>(source)); // use indices as intended indices->swap(reinterpret_cast<std::vector<int>&>(pcout.points)); 

Notice how I need to use indexes as const shared_ptr. I believe that the distributor will not play a role in the swap operation. Ints also should not have any alignment that needs to be aligned, as they already have 32-bit size. The std :: allocator version should be able to read from the aligned version, since it can only allocate memory addresses that std :: allocator could use anyway. Finally, I am exchanging back because the aligned dispenser may crash if it tries to remove the reserved space without alignment.

I tried, and it didn’t work, but it’s not enough to convince me that it is really correct. It is safe? If not, is it conditionally safe if certain reasonable assumptions are made regarding the compiler? Is there a safer alternative that does not have a noticeable effect on performance?

Please do not answer "profile your code", "not worth it" or similar answers. Even if they are applicable here, there is theoretically a scenario where copying is not a viable solution, and this thread should address this.

A similar question is about copying data in its pure form, as explained in the comments.

EDIT: it seems that even though Eigen :: aligned_allocator is for 16-bit alignment, an extra padding is not added to the int. Comparing the addresses of the first and last elements in the list gives the size that you would expect from the number of elements and sizeof (int). This means that ints are stored in a way that should be compatible with the version of std :: allocator. I hope I will have time later or in the coming days to conduct a more complete test.

+5
source share
1 answer

If you have the opportunity to change the function prototype to a different type of vector, then the standard library has a completely new namespace ( namespace pmr ) that uses style erasure for dispensers to ensure compatibility between containers using different dispensers.

See polymorphic_allocator for more details : when and why should I use it?

With this change you can just do

 void foo(std::pmr::vector<int>& vec); 

and pass a vector type with any allocator allocated to you (if it is also std::pmr::vector ).

If you cannot change the type of vector that the function expects, I don't think you can do much better than copying / moving elements one at a time.

reinterpret_cast using two different vector instances for different types and then using methods on them is very dangerous.

+2
source

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


All Articles