Last active
February 25, 2025 10:50
-
-
Save dk949/8ef8270dc442e4bc4ef355244cd1b78d to your computer and use it in GitHub Desktop.
realloc for unique_ptr
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
`realloc` functionality for `std::uniqur_ptr` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment