diff --git a/doc/smart_ptr/allocate_unique.adoc b/doc/smart_ptr/allocate_unique.adoc index 7e3026c..0b6f173 100644 --- a/doc/smart_ptr/allocate_unique.adoc +++ b/doc/smart_ptr/allocate_unique.adoc @@ -1,5 +1,5 @@ //// -Copyright 2019 Glen Joseph Fernandes (glenjofe@gmail.com) +Copyright 2019-2021 Glen Joseph Fernandes (glenjofe@gmail.com) Distributed under the Boost Software License, Version 1.0. @@ -85,6 +85,11 @@ namespace boost { template std::unique_ptr[], alloc_noinit_deleter> allocate_unique_noinit(const A& a); + + template + allocator_pointer_t>>> + get_allocator_pointer(const std::unique_ptr>& p) noexcept; } ``` @@ -269,6 +274,18 @@ Returns:: A `std::unique_ptr` to a sequence of `extent_v` default-initialized objects of type `remove_extent_t`. Example:: `auto p = allocate_unique_noinit(a);` +``` +template + allocator_pointer_t>>> + get_allocator_pointer(const std::unique_ptr>& p) noexcept; +``` +[none] +* {blank} ++ +Returns:: The allocator pointer to the allocation. +Example:: `auto r = boost::get_allocator_ptr(p.release());` + ## Deleter Class template `alloc_deleter` is the deleter used by the `allocate_unique` diff --git a/include/boost/smart_ptr/allocate_unique.hpp b/include/boost/smart_ptr/allocate_unique.hpp index 3738b38..07cc2bf 100644 --- a/include/boost/smart_ptr/allocate_unique.hpp +++ b/include/boost/smart_ptr/allocate_unique.hpp @@ -1,5 +1,5 @@ /* -Copyright 2019 Glen Joseph Fernandes +Copyright 2019-2021 Glen Joseph Fernandes (glenjofe@gmail.com) Distributed under the Boost Software License, Version 1.0. @@ -477,6 +477,15 @@ allocate_unique(const A& alloc, return c.release(); } +template +inline typename allocator_pointer::type>::type>::type +get_allocator_pointer(const std::unique_ptr >& p) BOOST_NOEXCEPT +{ + return p.get().ptr(); +} + } /* boost */ #endif diff --git a/test/Jamfile b/test/Jamfile index 72c1a17..5d32880 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -352,6 +352,7 @@ run allocate_unique_noinit_test.cpp ; run allocate_unique_test.cpp ; run allocate_unique_throws_test.cpp ; run allocate_unique_value_test.cpp ; +run get_allocator_pointer_test.cpp ; run sp_guides_test.cpp ; run sp_guides_test2.cpp ; diff --git a/test/get_allocator_pointer_test.cpp b/test/get_allocator_pointer_test.cpp new file mode 100644 index 0000000..e59b2f9 --- /dev/null +++ b/test/get_allocator_pointer_test.cpp @@ -0,0 +1,250 @@ +/* +Copyright 2021 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#if (!defined(BOOST_LIBSTDCXX_VERSION) || \ + BOOST_LIBSTDCXX_VERSION >= 46000) && \ + !defined(BOOST_NO_CXX11_SMART_PTR) +#include +#include + +template +class point { +public: + point() + : state_() + , ptr_() { } + + point(int count, T* value) + : state_(count) + , ptr_(value) { } + + operator bool() const { + return static_cast(ptr_); + } + + T* operator->() const { + return ptr_; + } + + int state() const { + return state_; + } + +private: + int state_; + T* ptr_; +}; + +template +class creator { +public: + typedef T value_type; + typedef point pointer; + typedef std::ptrdiff_t difference_type; + + creator() + : state_() { } + + explicit creator(int value) + : state_(value) { } + + template + creator(const creator& other) + : state_(other.state()) { } + + pointer allocate(std::size_t size) { + return pointer(state_, + static_cast(::operator new(sizeof(T) * size))); + } + + void deallocate(pointer ptr, std::size_t) { + ::operator delete(ptr.operator->()); + } + + int state() const { + return state_; + } + +private: + int state_; +}; + +template +inline bool +operator==(const creator&, const creator&) +{ + return true; +} + +template +inline bool +operator!=(const creator&, const creator&) +{ + return false; +} + +int main() +{ + { + std::unique_ptr > > result = + boost::allocate_unique(creator<>(1)); + point ptr = boost::get_allocator_pointer(result); + BOOST_TEST_EQ(ptr.state(), 1); + } + { + std::unique_ptr > > result = + boost::allocate_unique(creator<>(2)); + point ptr = boost::get_allocator_pointer(result); + BOOST_TEST_EQ(ptr.state(), 2); + } + { + std::unique_ptr > > result = + boost::allocate_unique(creator<>(3), 3); + point ptr = boost::get_allocator_pointer(result); + BOOST_TEST_EQ(ptr.state(), 3); + } + { + std::unique_ptr > > result = + boost::allocate_unique(creator<>(4)); + point ptr = boost::get_allocator_pointer(result); + BOOST_TEST_EQ(ptr.state(), 4); + } + { + std::unique_ptr > > result = + boost::allocate_unique(creator<>(5), 2); + point ptr = boost::get_allocator_pointer(result); + BOOST_TEST_EQ(ptr.state(), 5); + } + { + std::unique_ptr > > result = + boost::allocate_unique(creator<>(6)); + point ptr = boost::get_allocator_pointer(result); + BOOST_TEST_EQ(ptr.state(), 6); + } + { + std::unique_ptr > > result = + boost::allocate_unique(creator<>(7), 3); + point ptr = boost::get_allocator_pointer(result); + BOOST_TEST_EQ(ptr.state(), 7); + } + { + std::unique_ptr > > result = + boost::allocate_unique(creator<>(8)); + point ptr = boost::get_allocator_pointer(result); + BOOST_TEST_EQ(ptr.state(), 8); + } + { + std::unique_ptr > > result = + boost::allocate_unique(creator<>(9), 2); + point ptr = boost::get_allocator_pointer(result); + BOOST_TEST_EQ(ptr.state(), 9); + } + { + std::unique_ptr > > result = + boost::allocate_unique(creator<>(10)); + point ptr = boost::get_allocator_pointer(result); + BOOST_TEST_EQ(ptr.state(), 10); + } + { + std::unique_ptr > > > result = + boost::allocate_unique_noinit(creator<>(11)); + point ptr = boost::get_allocator_pointer(result); + BOOST_TEST_EQ(ptr.state(), 11); + } + { + std::unique_ptr > > > result = + boost::allocate_unique_noinit(creator<>(12)); + point ptr = boost::get_allocator_pointer(result); + BOOST_TEST_EQ(ptr.state(), 12); + } + { + std::unique_ptr > > > result = + boost::allocate_unique_noinit(creator<>(13), 3); + point ptr = boost::get_allocator_pointer(result); + BOOST_TEST_EQ(ptr.state(), 13); + } + { + std::unique_ptr > > > result = + boost::allocate_unique_noinit(creator<>(14)); + point ptr = boost::get_allocator_pointer(result); + BOOST_TEST_EQ(ptr.state(), 14); + } + { + std::unique_ptr > > > result = + boost::allocate_unique_noinit(creator<>(15), 2); + point ptr = boost::get_allocator_pointer(result); + BOOST_TEST_EQ(ptr.state(), 15); + } + { + std::unique_ptr > > > result = + boost::allocate_unique_noinit(creator<>(16)); + point ptr = boost::get_allocator_pointer(result); + BOOST_TEST_EQ(ptr.state(), 16); + } + { + std::unique_ptr > > > result = + boost::allocate_unique_noinit(creator<>(17), 3); + point ptr = boost::get_allocator_pointer(result); + BOOST_TEST_EQ(ptr.state(), 17); + } + { + std::unique_ptr > > > result = + boost::allocate_unique_noinit(creator<>(18)); + point ptr = boost::get_allocator_pointer(result); + BOOST_TEST_EQ(ptr.state(), 18); + } + { + std::unique_ptr > > > result = + boost::allocate_unique_noinit(creator<>(19), 2); + point ptr = boost::get_allocator_pointer(result); + BOOST_TEST_EQ(ptr.state(), 19); + } + { + std::unique_ptr > > > result = + boost::allocate_unique_noinit(creator<>(20)); + point ptr = boost::get_allocator_pointer(result); + BOOST_TEST_EQ(ptr.state(), 20); + } + return boost::report_errors(); +} +#else +int main() +{ + return 0; +} +#endif