Getting Howard Hinnant short_alloc (C ++ 11 version) for compilation in Visual C ++ 2015

I would like to use a custom allocator with std :: vector so that small data buffers are stored on the stack (say, less than 1024 bytes) and only longer vectors are stored on the heap. As a person who has a background in Fortran, he hurts me physically every time I have to allocate heap memory to store half a dozen items throughout a five-line subroutine!

Howard Hinnant has published his short_alloc distributor, which does exactly what I'm looking for, and if I compile it with gcc, it will work. However, in Visual C ++, I cannot compile it. In Visual C ++ 2013, part of the problem was that too many C ++ 11 keywords were unsupported, but I still ran into the problem even when I had # DEFINE'd all these away. Today I tried compiling in Visual C ++ 2015 CTP 5, and now all keywords are supported, but compilation ultimately does not work for the same reason.

The problem is this: for some reason I cannot claim complete understanding, the Hinnant code uses the copy constructor by default, but removes the copy assignment operator:

short_alloc(const short_alloc&) = default; short_alloc& operator=(const short_alloc&) = delete; 

When trying to compile this causes the following error in Visual C ++:

 xmemory0(892): error C2280: 'short_alloc<int,1024> &short_alloc<1024>::operator =(const short_alloc<1024> &)': attempting to reference a deleted function 

Which confuses me even more if I change the Hinnant code to say

 short_alloc(const short_alloc&) = default; short_alloc& operator=(const short_alloc&) = default; 

... then I get exactly the same error message.

For reference, here is my test code:

 #include <iostream> #include <vector> #include "short_alloc.h" void populate_the_vector(std::vector<int, short_alloc<int, 1024> > &theVector) { arena<1024> B; std::vector<int, short_alloc<int, 1024> > anothertestvec{(short_alloc<int, 1024>(B))}; anothertestvec.resize(10); for (int i=0; i<10; ++i) { anothertestvec[i] = i; } theVector = std::move(anothertestvec); // Actually causes a copy, as the Arenas are different } int main() { arena<1024> A; std::vector<int, short_alloc<int, 1024> > testvec{(short_alloc<int, 1024>(A))}; populate_the_vector(testvec); printf("Testvec(10)=%d\r\n", testvec[5]); return 0; } 

The compilation error disappears if I comment on the line in which

 theVector = std::move(anothertestvec); 

obviously, the main problem is that Visual C ++ approaches the copy differently from gcc. Despite this, I do not understand how to proceed from here. Is there a way to make this work in Visual C ++?

+6
source share
1 answer

The easiest hack I can think of replaces

 short_alloc& operator=(const short_alloc&) = delete; 

with

 short_alloc& operator=(const short_alloc&) { assert(false && "this should never be called"); return *this; }; 

It looks pretty dangerous, but actually it is not so bad in this particular case, and here's why:

The reason the original version is not compiled in VC ++ is because its standard implementation of the std::vector move operator library assigns a classic error when testing std::allocator_traits<...>::propagate_on_container_move_assignment::value with if() instructions.

It performs a proper check and does not assign a allocator if the attribute value is false (and moves the elements separately to the other side, if the distributors are different, in accordance with the requirements of the standard), but the code to the if() branch should still be compiled, although it never will be achieved for this type of distributor.

So, this assignment operator will never be called by the container implementation at runtime, and therefore the hack is safe in this particular case.

(The funny thing is that on the one line below if() , the actual move is performed correctly using an auxiliary function by sending a tag ...)


This is based on the standard library implementation that comes with the Visual C ++ 2013 4 update.

Update: as reported by OP in the comments, the VC14 CTP5 has the same problem.


Update 2: as indicated in the comments to the bug report , a fix for this problem will be available in the final version of Visual C ++ 2015.

+9
source

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


All Articles