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