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
stdprovided 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, invokesconstruct_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.
