Skip to content

Instantly share code, notes, and snippets.

@dk949
Last active February 25, 2025 10:50
Show Gist options
  • Save dk949/8ef8270dc442e4bc4ef355244cd1b78d to your computer and use it in GitHub Desktop.
Save dk949/8ef8270dc442e4bc4ef355244cd1b78d to your computer and use it in GitHub Desktop.
realloc for unique_ptr
#ifndef UT_REALLOC_UNIQUE_PTR_HPP
#define UT_REALLOC_UNIQUE_PTR_HPP
#include <memory>
#include <utility>
/**Usage:
* std >= c++17
*
* #include "realloc_unique_ptr.hpp"
* #include <cstdio>
* #include <cstring>
*
* int main() {
* // please use std::string instead of this!
* std::unique_ptr<char[]> ptr {new char[] {"hello"}};
* auto const size = std::strlen(ptr.get()) + 1;
* ptr = ut::realloc(std::move(ptr), size, 12);
* std::strcat(ptr.get(), " world");
* std::puts(ptr.get());
* // output: "hello world"
* }
*/
namespace ut {
/** realloc for unique_ptr
*
* The address of the pointer will always change. **All non owning references to the pointer become invalid**
*
* `new_size` can be larger or smaller than `old_size` (I guess it can be the same as `old_size` too, but
* that's not very useful).
*
* Differences with libc realloc:
* * Sizes are expressed in number of elements of `T` (not bytes)
* * Requires the number of elements the old pointer points to, since there is no standard way of obtaining
* that.
* * Created memeory will be default initialised (created with new[])
* * **Unless it's a builtin type, then it will not be initialised**
* * If a type is not trivially copyable, but can be nothrow-move-assigned, it will be moved
* * Trivial types will still be memcpy-ed when optimisations are on (on GCC with -O1 and above)
* * In all other cases the values will be copied one by one (i.e. invoking the copy assignment operator).
*
* NOTE: if you're reading this and know a way to avoid default initialising the values (at least the ones
* copied from the old pointer) please leave a comment.
*
* The use of this function is highly discouraged, please use std::vector if you can. It was designed for C API interop.
*/
template<typename T>
[[nodiscard("Discarding the reuturned value will free the memeory it points to")]]
std::unique_ptr<T[]> realloc(std::unique_ptr<T[]> ptr, std::size_t old_size, std::size_t new_size) {
auto *const begin = ptr.get();
auto *const end = begin + std::min(old_size, new_size);
auto *out_ptr = new T[new_size];
if constexpr (std::is_nothrow_move_assignable_v<T>)
// NOTE: for trivial types this becomes a memcpy
std::move(begin, end, out_ptr);
else
std::copy(begin, end, out_ptr);
return std::unique_ptr<T[]> {out_ptr};
}
} // namespace ut
#endif // UT_REALLOC_UNIQUE_PTR_HPP
`realloc` functionality for `std::uniqur_ptr`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment