c++templatesallocator

Is it possible to override the default Allocator in C++ with out manualy specifying it in each constructor


C++ standard library containers such as std::vector accept an optional template parameter that lets you specify an alternate allocator. The examples I can find show this happening at each object creation via the syntax:

std::vector<T,custom::custom_allocator<T> >

Is there a way to globally set custom::custom_allocator<T> such that I don't need to include it in the template arguments every time? Preference would be for solutions that do not require wrapping the stl in custom code, or using processor text substitution.


Solution

  • I generally find namespaces a good way of separating own and third party code. They can be used in various ways to organize self documentig code. For this case I would regroup all my required containers in a namespace:

    namespace my_containers{
        template <
            typename T,
            typename alloc = custom_allocator<T>
        > using vector = std::vector<T,alloc>;
    
        template <
            typename C,
            typename trait = std::char_traits<C>,
            typename alloc = custom_allocator<C>
        > using basic_string = std::basic_string<C, trait, alloc>;
    
        using string = basic_string<char>;
    
        /*Define aliases for other template types*/
    };
    

    Now you can switch with a compiler defined macro:

    #ifdef USE_STL
        namespace containers = std;
    #else 
        namespace containers = my_containers;
    #endif
    

    And a local namespace injection in function scope is not bad:

    void foo(){
       using namespace containers;
       vector<int> my_vec;
       string my_str;
       /*Blah blah*/
    };
    

    By introducing an extra boolean argument, I could ditch the preprocessor like this:

    namespace containers{
    
        constexpr bool use_stl = false;
    
        template <typename T>
        using allocator = std::conditional_t <
            use_stl,
            std::allocator<T>,
            custom_allocator<T>
        >; // allocator<T,choice>
    
        template <
            typename T,
            typename alloc = allocator<T>
        > using vector = std::vector<T,alloc>;
    
       /*Do the same for string and rest*/
    };
    

    By changing the value of use_stl you can choose the desired implementation at compile-time.