0

I have a custom allocator for a vector, but I would rather not have it in the code everywhere. So I thought to cast it to a normal vector

vector<Complex> * createVector(size_t nfft)
{
    vector<Complex,fftalloc<Complex > > * data = new vector<Complex,fftalloc<Complex > >(nfft);
    return reinterpret_cast<vector<Complex> *>(data);
}

my allocator/deallocator functions print out if they are called:

   pointer allocate (size_type num, const void* = 0) {
       // print message and allocate memory with global new
       ALLOCDEBUG << "allocate " << num << " element(s)"
       ...
   }

   void deallocate (pointer p, size_type num) {
       // print message and deallocate memory with global delete
       ALLOCDEBUG << "deallocate " << num << " element(s)"
       ...
   }

But a test with

    {
        vector<complex<double> > * v;
        v = fft.createVector(16);
        v->push_back(1);
        delete v;
    }

prints out only the allocate function.

Is it possible to cast without loosing the deallocator?

Matthias Pospiech
  • 3,130
  • 18
  • 55
  • 76
  • 4
    No, `reinterpret_cast` is really bad idea. It could possibly even crash your app. Vectors with different allocator are not compatible types and you should never use `reinterpret_cast` unless you really need to and know what you are doing (as you obviously do not here). – firda Mar 29 '16 at 07:46
  • Why not do something like `template using fft_vector = std::vector>;`? Then you would just pass `fft_vector` around. – TartanLlama Mar 29 '16 at 07:50
  • Thats obvious, but I do not like to use or introduce custom types. I once had a application using a custom CComplex everywhere. I had to rewrite it to make it reusable. – Matthias Pospiech Mar 29 '16 at 07:52
  • 1
    "Is it possible to cast without loosing the deallocator?" - unfortunately, absolutely not (IMHO). – Ami Tavory Mar 29 '16 at 07:54
  • In theory you can use `polymorphic_allocator` from `std::experimental::pmr`, if your compiler supports it, to avoid many types floating around. I do not remember if it made into C++17, but if it did, I expect any major compiler to have support for it already. – Revolver_Ocelot Mar 29 '16 at 07:56
  • Ok the answer that it is not possible is what I needed to know. Future code is not what I like to play around, though its interesting. – Matthias Pospiech Mar 29 '16 at 08:06

2 Answers2

2

The problem here is that the allocator is a property of the template, not stored as part of the vector or something. So when you cast from one type of vector to another, you are changing allocator element of the template type.

The simplest way [in terms of typing] to solve this is to declare a type, e.g. typedef vector<double, fft_alloc<double> > fftdouble; - using template declaration can help to make many such types.

You can't swap and change which allocator you use, and there is no trivial solution [in current standards].

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
0

casting a pointer to A into a pointer to B, where B is not in the same inheritance hierarchy as A, and then using the pointer to B for anything other than casting back to a pointer to A is undefined behaviour.

Once we invoke undefined behaviour, all discussion must end because we are no longer in a position to reason about the behaviour of any part of the program.

vector<Complex,fftalloc<Complex > > is not the same type as vector<Complex> *> in any way, shape or form.

casting between them makes no sense whatsoever.

I would be interested to understand what you are really trying to acheive here. The custom allocator in the first vector only controls the allocation of memory in which to store the complex numbers. Since the code is seeking to cast away sight of the allocator, one could conclude that you don't intend to increase the vector's length going forward. In which case, the question is begged, since the allocation happens only once, why bother with the custom allocator at all?

Richard Hodges
  • 68,278
  • 7
  • 90
  • 142