Search code examples
c++templatesc++17template-specializationclass-template

How to change/set template parameter based on type?


I want to create a static class, which will act as fixed size memory allocator.

Lets look at this simplified example:

struct A {};
struct B {};

template<class T, std::size_t MaxNumObjects>
class InternalContainer
{
public:
    static constexpr std::size_t maxObjects = MaxNumObjects;

    static T* createObject()
    {
        return ::new(&objects[idx++]) T;
    }
    static T* releaseObject() { /*...*/ };

private:
    using buffer_t = std::aligned_storage_t<sizeof(T), alignof(T)>;
    static buffer_t objects[maxObjects];
    static std::size_t idx;
};

A* a = InternalContainer<A, 2>::createObject();
B* b = InternalContainer<B, 5>::createObject();

How can I predefine the maximum size of the container based on type?

// will be replaced "InternalContainer<A, 2>"
A* a = MyContainer<A>::createObject(); 

// will be replaced "InternalContainer<B, 5>"
B* b = MyContainer<B>::createObject();

I have tried something like this, but it does not work:

template<class T>
using MyContainer = InternalContainer<A, 2>;
template<class T>
using MyContainer = InternalContainer<B, 5>;

Solution

  • This can be easily accomplished by explicitly specializing a variable template, e.g.:

    godbolt example

    struct A {};
    struct B {};
    struct C {};
    
    // default size for all InternalContainers
    template<class T>
    constexpr std::size_t InternalContainerDefaultSize = 64;
    // specialization for A
    template<>
    constexpr std::size_t InternalContainerDefaultSize<A> = 2;
    // specialization for B
    template<>
    constexpr std::size_t InternalContainerDefaultSize<B> = 5;
    
    template<class T, std::size_t MaxNumObjects = InternalContainerDefaultSize<T>>
    class InternalContainer {
        /* ... */
    };
    
    
    InternalContainer<A> aContainer; // size will be 2
    InternalContainer<B> bContainer; // size will be 5
    InternalContainer<C> cContainer; // size will be 64
    
    // default size can be overriden by explicitly specifying another size
    InternalContainer<A, 10> aContainer; // size will be 10