diff --git a/include/boost/smart_ptr/allocation_ptr.hpp b/include/boost/smart_ptr/allocation_ptr.hpp new file mode 100644 index 0000000..6cf5d51 --- /dev/null +++ b/include/boost/smart_ptr/allocation_ptr.hpp @@ -0,0 +1,218 @@ +/* +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_SMART_PTR_ALLOCATION_PTR_HPP +#define BOOST_SMART_PTR_ALLOCATION_PTR_HPP + +#include +#include +#include +#if !defined(BOOST_NO_CXX11_ALLOCATOR) +#include +#endif + +namespace boost { +namespace detail { + +template +struct sp_allocation_ptr { +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + typedef typename std::allocator_traits::template + rebind_traits::pointer type; +#else + typedef typename A::template rebind::other::pointer type; +#endif +}; + +} /* detail */ + +template +class allocation_ptr { +public: + typedef typename detail::sp_allocation_ptr::type pointer; + typedef T element_type; + + allocation_ptr() BOOST_SP_NOEXCEPT + : p_() { } + +#if !defined(BOOST_NO_CXX11_NULLPTR) + allocation_ptr(detail::sp_nullptr_t) BOOST_SP_NOEXCEPT + : p_() { } +#endif + + explicit allocation_ptr(pointer p) BOOST_SP_NOEXCEPT + : p_(p) { } + + T& operator*() const { + return *p_; + } + + pointer operator->() const BOOST_SP_NOEXCEPT { + return p_; + } + + pointer get() const BOOST_SP_NOEXCEPT { + return p_; + } + +#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) + explicit operator bool() const BOOST_SP_NOEXCEPT { + return static_cast(p_); + } +#endif + + bool operator!() const BOOST_SP_NOEXCEPT { + return !p_; + } + +private: + pointer p_; +}; + +template +class allocation_ptr { +public: + typedef typename detail::sp_allocation_ptr::type pointer; + typedef T element_type; + + allocation_ptr() BOOST_SP_NOEXCEPT + : p_() + , n_() { } + +#if !defined(BOOST_NO_CXX11_NULLPTR) + allocation_ptr(detail::sp_nullptr_t) BOOST_SP_NOEXCEPT + : p_() + , n_() { } +#endif + + allocation_ptr(pointer p, std::size_t n) BOOST_SP_NOEXCEPT + : p_(p) + , n_(n) { } + + T& operator[](std::size_t i) const BOOST_SP_NOEXCEPT_WITH_ASSERT { + BOOST_ASSERT(i < n_); + return p_[i]; + } + + pointer get() const BOOST_SP_NOEXCEPT { + return p_; + } + + std::size_t size() const BOOST_SP_NOEXCEPT { + return n_; + } + +#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) + explicit operator bool() const BOOST_SP_NOEXCEPT { + return static_cast(p_); + } +#endif + + bool operator!() const BOOST_SP_NOEXCEPT { + return !p_; + } + +private: + pointer p_; + std::size_t n_; +}; + +template +class allocation_ptr { +public: + typedef typename detail::sp_allocation_ptr::type pointer; + typedef T element_type; + + allocation_ptr() BOOST_SP_NOEXCEPT + : p_() { } + +#if !defined(BOOST_NO_CXX11_NULLPTR) + allocation_ptr(detail::sp_nullptr_t) BOOST_SP_NOEXCEPT + : p_() { } +#endif + + explicit allocation_ptr(pointer p) BOOST_SP_NOEXCEPT + : p_(p) { } + + T& operator[](std::size_t i) const BOOST_SP_NOEXCEPT_WITH_ASSERT { + BOOST_ASSERT(i < N); + return p_[i]; + } + + pointer get() const BOOST_SP_NOEXCEPT { + return p_; + } + + static std::size_t size() BOOST_SP_NOEXCEPT { + return N; + } + +#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) + explicit operator bool() const BOOST_SP_NOEXCEPT { + return static_cast(p_); + } +#endif + + bool operator!() const BOOST_SP_NOEXCEPT { + return !p_; + } + +private: + pointer p_; +}; + +template +inline bool +operator==(const allocation_ptr& lhs, const allocation_ptr& rhs) +{ + return lhs.get() == rhs.get(); +} + +template +inline bool +operator!=(const allocation_ptr& lhs, const allocation_ptr& rhs) +{ + return !(lhs == rhs); +} + +#if !defined(BOOST_NO_CXX11_NULLPTR) +template +inline bool +operator==(const allocation_ptr& lhs, + detail::sp_nullptr_t) BOOST_SP_NOEXCEPT +{ + return !lhs.get(); +} + +template +inline bool +operator==(detail::sp_nullptr_t, + const allocation_ptr& rhs) BOOST_SP_NOEXCEPT +{ + return !rhs.get(); +} + +template +inline bool +operator!=(const allocation_ptr& lhs, + detail::sp_nullptr_t) BOOST_SP_NOEXCEPT +{ + return static_cast(lhs.get()); +} + +template +inline bool +operator!=(detail::sp_nullptr_t, + const allocation_ptr& rhs) BOOST_SP_NOEXCEPT +{ + return static_cast(rhs.get()); +} +#endif + +} /* boost */ + +#endif diff --git a/test/Jamfile b/test/Jamfile index 02a8a2e..7bc3651 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -319,3 +319,5 @@ run get_deleter_test3.cpp : : : off gcc-4.4.7,0x:n run shared_from_test.cpp ; run weak_from_test.cpp ; run weak_from_test2.cpp ; + +run allocation_ptr_test.cpp ; diff --git a/test/allocation_ptr_test.cpp b/test/allocation_ptr_test.cpp new file mode 100644 index 0000000..5218484 --- /dev/null +++ b/test/allocation_ptr_test.cpp @@ -0,0 +1,426 @@ +/* +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include +#include + +struct scalar { }; +struct unbounded_array { }; +struct bounded_array { }; + +void test_pointer(scalar) +{ + BOOST_TEST_TRAIT_SAME(boost::allocation_ptr >::pointer, int*); +} + +void test_pointer(unbounded_array) +{ + BOOST_TEST_TRAIT_SAME(boost::allocation_ptr >::pointer, int*); +} + +void test_pointer(bounded_array) +{ + BOOST_TEST_TRAIT_SAME(boost::allocation_ptr >::pointer, int*); +} + +void test_element_type(scalar) +{ + BOOST_TEST_TRAIT_SAME(boost::allocation_ptr >::element_type, int); +} + +void test_element_type(unbounded_array) +{ + BOOST_TEST_TRAIT_SAME(boost::allocation_ptr >::element_type, int); +} + +void test_element_type(bounded_array) +{ + BOOST_TEST_TRAIT_SAME(boost::allocation_ptr >::element_type, int); +} + +void test_default_construct(scalar) +{ + BOOST_TEST_NOT((boost::allocation_ptr >().get())); +} + +void test_default_construct(unbounded_array) +{ + BOOST_TEST_NOT((boost::allocation_ptr >().get())); +} + +void test_default_construct(bounded_array) +{ + BOOST_TEST_NOT((boost::allocation_ptr >().get())); +} + +#if !defined(BOOST_NO_CXX11_NULLPTR) +void test_nullptr_construct(scalar) +{ + BOOST_TEST_NOT((boost::allocation_ptr >(nullptr).get())); +} + +void test_nullptr_construct(unbounded_array) +{ + BOOST_TEST_NOT((boost::allocation_ptr >(nullptr).get())); +} + +void test_nullptr_construct(bounded_array) +{ + BOOST_TEST_NOT((boost::allocation_ptr >(nullptr).get())); +} +#endif + +void test_access(scalar) +{ + boost::default_allocator a; + int* v = a.allocate(1); + ::new(v) int(5); + BOOST_TEST_EQ((*boost::allocation_ptr >(v)), 5); + BOOST_TEST_EQ((boost::allocation_ptr >(v).operator->()), v); + a.deallocate(v, 1); +} + +void test_access(unbounded_array) +{ + boost::default_allocator a; + int* v = a.allocate(3); + ::new(v) int(5); + boost::allocation_ptr > p(v, 3); + BOOST_TEST_EQ(p[0], 5); + BOOST_TEST_EQ(p.size(), 3); + a.deallocate(v, 3); +} + +void test_access(bounded_array) +{ + boost::default_allocator a; + int* v = a.allocate(1); + ::new(v) int(5); + boost::allocation_ptr > p(v); + BOOST_TEST_EQ(p[0], 5); + BOOST_TEST_EQ(p.size(), 3); + a.deallocate(v, 1); +} + +#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) +void test_bool(scalar) +{ + BOOST_TEST_NOT((boost::allocation_ptr >())); + boost::default_allocator a; + int* v = a.allocate(1); + BOOST_TEST((boost::allocation_ptr >(v))); + a.deallocate(v, 1); +} + +void test_bool(unbounded_array) +{ + BOOST_TEST_NOT((boost::allocation_ptr >())); + boost::default_allocator a; + int* v = a.allocate(3); + BOOST_TEST((boost::allocation_ptr >(v, 3))); + a.deallocate(v, 3); +} + +void test_bool(bounded_array) +{ + BOOST_TEST_NOT((boost::allocation_ptr >())); + boost::default_allocator a; + int* v = a.allocate(1); + BOOST_TEST((boost::allocation_ptr >(v))); + a.deallocate(v, 1); +} +#endif + +void test_not(scalar) +{ + BOOST_TEST((!boost::allocation_ptr >())); + boost::default_allocator a; + int* v = a.allocate(1); + BOOST_TEST_NOT((!boost::allocation_ptr >(v))); + a.deallocate(v, 1); +} + +void test_not(unbounded_array) +{ + BOOST_TEST((!boost::allocation_ptr >())); + boost::default_allocator a; + int* v = a.allocate(3); + BOOST_TEST_NOT((!boost::allocation_ptr >(v, 3))); + a.deallocate(v, 3); +} + +void test_not(bounded_array) +{ + BOOST_TEST((!boost::allocation_ptr >())); + boost::default_allocator a; + int* v = a.allocate(1); + BOOST_TEST_NOT((!boost::allocation_ptr >(v))); + a.deallocate(v, 1); +} + +void test_equal(scalar) +{ + boost::allocation_ptr > p1; + BOOST_TEST(p1 == p1); + boost::default_allocator a; + int* v1 = a.allocate(1); + boost::allocation_ptr > p2(v1); + BOOST_TEST(p2 == p2); + BOOST_TEST_NOT(p1 == p2); + BOOST_TEST_NOT(p2 == p1); + boost::allocation_ptr > p3(v1); + BOOST_TEST(p3 == p2); + BOOST_TEST(p2 == p3); + int* v2 = a.allocate(1); + boost::allocation_ptr > p4(v2); + BOOST_TEST_NOT(p2 == p4); + BOOST_TEST_NOT(p4 == p2); + a.deallocate(v2, 1); + a.deallocate(v1, 1); +} + +void test_equal(unbounded_array) +{ + boost::allocation_ptr > p1; + BOOST_TEST(p1 == p1); + boost::default_allocator a; + int* v1 = a.allocate(3); + boost::allocation_ptr > p2(v1, 3); + BOOST_TEST(p2 == p2); + BOOST_TEST_NOT(p1 == p2); + BOOST_TEST_NOT(p2 == p1); + boost::allocation_ptr > p3(v1, 3); + BOOST_TEST(p3 == p2); + BOOST_TEST(p2 == p3); + int* v2 = a.allocate(3); + boost::allocation_ptr > p4(v2, 3); + BOOST_TEST_NOT(p2 == p4); + BOOST_TEST_NOT(p4 == p2); + a.deallocate(v2, 3); + a.deallocate(v1, 3); +} + +void test_equal(bounded_array) +{ + boost::allocation_ptr > p1; + BOOST_TEST(p1 == p1); + boost::default_allocator a; + int* v1 = a.allocate(1); + boost::allocation_ptr > p2(v1); + BOOST_TEST(p2 == p2); + BOOST_TEST_NOT(p1 == p2); + BOOST_TEST_NOT(p2 == p1); + boost::allocation_ptr > p3(v1); + BOOST_TEST(p3 == p2); + BOOST_TEST(p2 == p3); + int* v2 = a.allocate(1); + boost::allocation_ptr > p4(v2); + BOOST_TEST_NOT(p2 == p4); + BOOST_TEST_NOT(p4 == p2); + a.deallocate(v2, 1); + a.deallocate(v1, 1); +} + +void test_not_equal(scalar) +{ + boost::allocation_ptr > p1; + BOOST_TEST_NOT(p1 != p1); + boost::default_allocator a; + int* v1 = a.allocate(1); + boost::allocation_ptr > p2(v1); + BOOST_TEST_NOT(p2 != p2); + BOOST_TEST(p1 != p2); + BOOST_TEST(p2 != p1); + boost::allocation_ptr > p3(v1); + BOOST_TEST_NOT(p3 != p2); + BOOST_TEST_NOT(p2 != p3); + int* v2 = a.allocate(1); + boost::allocation_ptr > p4(v2); + BOOST_TEST(p2 != p4); + BOOST_TEST(p4 != p2); + a.deallocate(v2, 1); + a.deallocate(v1, 1); +} + +void test_not_equal(unbounded_array) +{ + boost::allocation_ptr > p1; + BOOST_TEST_NOT(p1 != p1); + boost::default_allocator a; + int* v1 = a.allocate(3); + boost::allocation_ptr > p2(v1, 3); + BOOST_TEST_NOT(p2 != p2); + BOOST_TEST(p1 != p2); + BOOST_TEST(p2 != p1); + boost::allocation_ptr > p3(v1, 3); + BOOST_TEST_NOT(p3 != p2); + BOOST_TEST_NOT(p2 != p3); + int* v2 = a.allocate(3); + boost::allocation_ptr > p4(v2, 3); + BOOST_TEST(p2 != p4); + BOOST_TEST(p4 != p2); + a.deallocate(v2, 3); + a.deallocate(v1, 3); +} + +void test_not_equal(bounded_array) +{ + boost::allocation_ptr > p1; + BOOST_TEST_NOT(p1 != p1); + boost::default_allocator a; + int* v1 = a.allocate(1); + boost::allocation_ptr > p2(v1); + BOOST_TEST_NOT(p2 != p2); + BOOST_TEST(p1 != p2); + BOOST_TEST(p2 != p1); + boost::allocation_ptr > p3(v1); + BOOST_TEST_NOT(p3 != p2); + BOOST_TEST_NOT(p2 != p3); + int* v2 = a.allocate(1); + boost::allocation_ptr > p4(v2); + BOOST_TEST(p2 != p4); + BOOST_TEST(p4 != p2); + a.deallocate(v2, 1); + a.deallocate(v1, 1); +} + +#if !defined(BOOST_NO_CXX11_NULLPTR) +void test_equal_nullptr(scalar) +{ + boost::allocation_ptr > p1; + BOOST_TEST(p1 == nullptr); + BOOST_TEST(nullptr == p1); + boost::default_allocator a; + int* v = a.allocate(1); + boost::allocation_ptr > p2(v); + BOOST_TEST_NOT(p2 == nullptr); + BOOST_TEST_NOT(nullptr == p2); + a.deallocate(v, 1); +} + +void test_equal_nullptr(unbounded_array) +{ + boost::allocation_ptr > p1; + BOOST_TEST(p1 == nullptr); + BOOST_TEST(nullptr == p1); + boost::default_allocator a; + int* v = a.allocate(3); + boost::allocation_ptr > p2(v, 3); + BOOST_TEST_NOT(p2 == nullptr); + BOOST_TEST_NOT(nullptr == p2); + a.deallocate(v, 1); +} + +void test_equal_nullptr(bounded_array) +{ + boost::allocation_ptr > p1; + BOOST_TEST(p1 == nullptr); + BOOST_TEST(nullptr == p1); + boost::default_allocator a; + int* v = a.allocate(1); + boost::allocation_ptr > p2(v); + BOOST_TEST_NOT(p2 == nullptr); + BOOST_TEST_NOT(nullptr == p2); + a.deallocate(v, 1); +} + +void test_not_equal_nullptr(scalar) +{ + boost::allocation_ptr > p1; + BOOST_TEST_NOT(p1 != nullptr); + BOOST_TEST_NOT(nullptr != p1); + boost::default_allocator a; + int* v = a.allocate(1); + boost::allocation_ptr > p2(v); + BOOST_TEST(p2 != nullptr); + BOOST_TEST(nullptr != p2); + a.deallocate(v, 1); +} + +void test_not_equal_nullptr(unbounded_array) +{ + boost::allocation_ptr > p1; + BOOST_TEST_NOT(p1 != nullptr); + BOOST_TEST_NOT(nullptr != p1); + boost::default_allocator a; + int* v = a.allocate(3); + boost::allocation_ptr > p2(v, 3); + BOOST_TEST(p2 != nullptr); + BOOST_TEST(nullptr != p2); + a.deallocate(v, 1); +} + +void test_not_equal_nullptr(bounded_array) +{ + boost::allocation_ptr > p1; + BOOST_TEST_NOT(p1 != nullptr); + BOOST_TEST_NOT(nullptr != p1); + boost::default_allocator a; + int* v = a.allocate(1); + boost::allocation_ptr > p2(v); + BOOST_TEST(p2 != nullptr); + BOOST_TEST(nullptr != p2); + a.deallocate(v, 1); +} +#endif + +template +void test(T tag) +{ + test_pointer(tag); + test_element_type(tag); + test_default_construct(tag); +#if !defined(BOOST_NO_CXX11_NULLPTR) + test_nullptr_construct(tag); +#endif + test_access(tag); +#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) + test_bool(tag); +#endif + test_not(tag); + test_equal(tag); + test_not_equal(tag); +#if !defined(BOOST_NO_CXX11_NULLPTR) + test_equal_nullptr(tag); + test_not_equal_nullptr(tag); +#endif +} + +int main() +{ + test(scalar()); + test(unbounded_array()); + test(bounded_array()); + return boost::report_errors(); +}