1

I've got a base class with a pure virtual function:

class Allocator 
{
public:
    template< class T >
    virtual T* allocate(T type) = 0;
};

with a derived class with a templated function which the design intent was to override this virtual function:

class StackAllocator: public Allocator 
{
public: 
    StackAllocator(size_t size, void* stackStart = nullptr);

    template< class T>
    T* allocate(T Type);
};

My design intent was to have allocate override the allocate in Allocator. But obviously after reading up on this, i have found the code above will not work.

I found alot of solutions that involve making the class itself a template, but in this situation i can't do this as the StackAllocator itself needs to be type-agnostic at compile. And only the function should deal with the varying types.

I found a work-around that involved making an 'allocation' class that was used on a per allocation basis that dealt with the allocation itself, but this seemed wasteful and not very clear in its application so now i'm stuck with simply getting rid of the virtual function and using just the derived class templated function.

Any ideas how i could do this? or ideas for how to rework my design? (bear in mind that i will be eventually making many more derived allocators so the base is necessary.)

Thanks!

Luke Bourne
  • 295
  • 2
  • 11
  • g++: error: templates may not be ‘virtual’ –  Apr 19 '16 at 10:29
  • @DieterLücking that's the whole point behind why he posted the question. he stated that he knows the code he posted can't work. – xaxxon Apr 19 '16 at 10:30
  • so something has to know the type it wants allocated -- either to template a class or to template a method in that class. What's the point of having a virtual function at all? this sounds like a pretty vanilla factory method/function/whatever. Some examples of how you think you'd use this if it worked would be helpful, though. Also, having something that returns a specific type requires something to accept that specific type, so you can't just call this generically... – xaxxon Apr 19 '16 at 10:32
  • Hey, the reason i'm using a virtual function is because i'm eventually going to build on what i've got to include a derived class of the StackAllocator (which will override allocate()). And also I will eventually be making other classes that derive from Allocator which are intended to override allocate. If i don't use the virtual function and just have the allocate()'s as standard member functions, all my code and the intended function works fine (for now), but i'm trying to think about how my code will later expand and the clarity of which it can be read. – Luke Bourne Apr 19 '16 at 10:43

2 Answers2

1

One possible way of solving this problem is to have a generic allocation function in the base class which simply allocates an array of bytes with some alignment:

virtual std::byte *allocate(size_t bytes, size_t align) = 0;

This function can be overridden in derived classes.

Then we can have a templated function in the base Allocator class which uses this non-templated function:

// Argument 'n' here can be the number of allocated instances...
// Not Necessary but might be useful
template<class T>
T *Allocator::allocate(size_t n)
{
  return (T *) allocate(sizeof(T) * n, alignof(T));
}

This way you have made it possible for derived classes to specifically implement their allocation strategy while retaining the typed-allocation API. The only caveat with this solution is that you will need to add using Allocator::allocate; somewhere in the derived class declaration (credits to Igor Tandetnik for this, explained here) but this is a simple thing to do.

Please keep in mind that using non-aligned pointers for arbitrary types is undefined behaviour and could have various undesireable effects: What exactly is an 'aligned pointer'?

Paul Deva
  • 11
  • 2
0

Imagine this code worked, how would you use it?

You'd have something that would be parameterized with the allocator, but since it returns the specific type, that thing would have to know what to do with that specific type. that means the code is either not generic (which means there's no reason to have a common base class because the code has to be specialized for the specific allocator type) or it is templated to take a matching type from the allocator, but then there's no reason to have a virtual function, since you can just create the very specific factory class (allocator) that matches the templated type of the thing using it.

You don't really want a templated allocate method - because a specific allocator subclass can't make any type. it can only make its one specific type. It sounds to me like maybe you want to use partial specialization to achieve this?

http://en.cppreference.com/w/cpp/language/partial_specialization

and use those partial specializations from something that is templated to the type that you want to create?

xaxxon
  • 19,189
  • 5
  • 50
  • 80