I am using a C framework (DPDK) which provides its own memory management facilities. Now I want to encapsulate these special pointers in an unique_ptr, which requires using a custom deleter (invoking the de-allocation function of the framework). To produce these pointers, I want to implement a factory function similar to make_unique.
I succeed in implementing this for non-array types, but fail for doing it for arrays:
template<typename T>
struct HugepageDeleter {
void operator()(T* b) { rte_free(b); }
};
template< typename T > using unique_hugepage = std::unique_ptr<T, HugepageDeleter<T>>;
/// std::make_unique for single objects
template<typename T, typename... Args>
unique_hugepage<T> make_unique_hugepage(Args&&... args)
{
void *ptr = rte_malloc(nullptr, sizeof(T), alignof(T));
auto t = new (ptr) T(std::forward<Args>(args)...);
return unique_hugepage<T>(t);
}
template<typename T>
unique_hugepage<T>
make_unique_hugepage_array(size_t num)
{
void *ptr = rte_malloc(nullptr, sizeof(std::remove_extent_t<T>[num]), alignof(T));
return unique_hugepage<std::remove_extent_t<T>[]>((std::remove_extent_t<T> *)ptr);
}
int test() {
unique_hugepage<int> p = make_unique_hugepage<int>();
auto testData = make_unique_hugepage_array<unsigned char[]>(16000);
}
Compiler output:
/usr/include/c++/10/bits/unique_ptr.h:612:17: error: no match for call to ‘(std::unique_ptr<unsigned char [], HugepageDeleter<unsigned char []> >::deleter_type {aka HugepageDeleter<unsigned char []>}) (unsigned char*&)’
612 | get_deleter()(__ptr);
| ~~~~~~~~~~~~~^~~~~~~
/.../HugepageMemory.h:14:10: note: candidate: ‘void HugepageDeleter<T>::operator()(T*) [with T = unsigned char []]’
14 | void operator()(T* b) { rte_free(b); }
| ^~~~~~~~
/.../HugepageMemory.h:14:24: note: no known conversion for argument 1 from ‘unsigned char*’ to ‘unsigned char (*)[]’
14 | void operator()(T* b) { rte_free(b); }
| ~~~^
I am using an zero-size struct as deleter, so that the unique_ptr can remain a zero-cost abstraction.