c++traitsallocatorspecialization

Partial template specialization for: std::allocator_traits?


Is it possible to specialize the std::allocator_traits, template like this?

namespace falloc_ {

  template<class Tp> class FAllocator ;

}

// partial spec for all falloc_::FAllocator<U>, std::allocator_traits

template<typename Tp> 
struct std::allocator_traits<falloc_::FAllocator<Tp> > {

 using allocator_type = falloc_::FAllocator<Tp> ;
 using value_type = typename allocator_type::value_type ;

 // ...
 // All the components I need here, I will include all the code if You need them.
 // ...

} ;


namespace falloc_ {

  template<class Tp> class FAllocator {

    public:
       using value_type = Tp ;
  
  } ;

}

The complete code compiles and runs in the std++20 allocator class and allocator, feature class (std::allocator_traits) specifications. In that case, my question is actually about practical correctness, whether according to people who know more about the standard, whether similar feature class overloading is forbidden, or simply assume that since the (complete) code is compileable and executable and works according to the intended plan - can I consider that I can use it?

Additionally, I tested the allocator with the code:

  std::vector<int, falloc_::FAllocator<int> > mv ;

  for (size_t i = 0 ; i < 5 ; i++) {
    mv.push_back(i) ;
  }

  for (int i = 4 ; i > -1 ; i--) {
    std::cout << "mv[" << i << "]: " << mv[i] << '\n' ;
  }

Memory was allocated and freed correctly, I also checked with, Valgrind. Using Gdb, I checked and all functions were called from

std::allocator_traits<falloc_::FAllocator<U> > // U aka int for std::vector<int, falloc_::FAllocator<int> > 

Thank You in advance for any insights, suggestions and advice.


Solution

  • Edit (February 22, 2023): As of C++23, it will no longer be permitted to specialize std::allocator_traits. See here for more information.

    Prior to C++23, it was permitted to specialize the std::allocator_traits template. See [namespace.std]/2:

    Unless explicitly prohibited, a program may add a template specialization for any standard library class template to namespace std provided that (a) the added declaration depends on at least one program-defined type and (b) the specialization meets the standard library requirements for the original template.

    The thing is that such specializations weren't particularly useful (which is why there wasn't much opposition to banning them in C++23). User specializations of standard library templates must meet all requirements of the original template. The standard specifies the definition of each member type of std::allocator_traits<A> and the behaviour of each member function to such an extent that if you were to write your own specialization, it would basically be identical to the original, which defeats the purpose of doing so. (I suppose you could have done something like add logging statements to std::allocator_traits<...>::construct(...) without violating the original requirements, but it's easier to just put those logging statements in the allocator itself, and from C++23 onward, that's what you'll have to do.)