Home > Mobile >  Is there an example of specializing std::allocator_traits::construct?
Is there an example of specializing std::allocator_traits::construct?

Time:04-19

I have the task of porting some code to c 20. Part of it is an templated allocator that handles some of the odd needs or Microsoft COM objects so we can use them in vectors. In part, it allocates/deallocates memory via CoTaskMemAlloc/CoTaskMemFree It also provides specializations of construct and destroy which have gone way in c 20.

For Example:

// VARIANT

inline void CnvCoTaskAlloc<VARIANT>::construct(VARIANT* p, const VARIANT& val){
    ::VariantCopy( p, const_cast<VARIANT*>( &val ) );
}

inline void CnvCoTaskAlloc<VARIANT>::destroy(VARIANT* p){
    ::VariantClear( p );
}

I am having a hard time working out how to migrate this code to c 20. If I could find an example of doing something similar that implements construct, I am pretty sure it would be obvious.

Thanks in Advance.

CodePudding user response:

The standard has the following to say about specializing standard library templates ([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 standard specifies the following behaviour for std::allocator_traits<Alloc>::construct ([allocator.traits.members]/5):

template<class T, class... Args>
  static constexpr void construct(Alloc& a, T* p, Args&&... args);

Effects: Calls a.construct(p, std::forward<Args>(args)...) if that call is well-formed; otherwise, invokes construct_at(p, std::forward<Args>(args)...).

So, if you choose to specialize std::allocator_traits<MyAlloc>::construct, it must do basically the same thing as the primary template: it will call MyAlloc::construct if possible, otherwise construct_at.

This suggests that specializing std::allocator_traits is generally not what you want to do. Instead, just like pre-C 20, you just need to make sure that MyAlloc::construct contains the logic that you want. If you want the default, you can even omit MyAlloc::construct entirely, and std::allocator_traits will take care of it.

  • Related