mirror of
https://github.com/boostorg/smart_ptr.git
synced 2025-07-30 20:57:21 +02:00
Add allocate_shared and make_shared for shared_ptr arrays of runtime size. Fulfills need for allocate_shared_array and make_shared_array.
[SVN r81219]
This commit is contained in:
49
include/boost/smart_ptr/allocate_shared_array.hpp
Normal file
49
include/boost/smart_ptr/allocate_shared_array.hpp
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012 Glen Joseph Fernandes
|
||||||
|
* glenfe at live dot com
|
||||||
|
*
|
||||||
|
* Distributed under the Boost Software License,
|
||||||
|
* Version 1.0. (See accompanying file LICENSE_1_0.txt
|
||||||
|
* or copy at http://boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
#ifndef BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP
|
||||||
|
#define BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP
|
||||||
|
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <boost/smart_ptr/detail/allocate_array_helper.hpp>
|
||||||
|
#include <boost/smart_ptr/detail/array_deleter.hpp>
|
||||||
|
#include <boost/smart_ptr/detail/sp_if_array.hpp>
|
||||||
|
#include <boost/type_traits/remove_cv.hpp>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
template<typename T, typename A>
|
||||||
|
inline typename detail::sp_if_array<T>::type
|
||||||
|
allocate_shared(const A& allocator, size_t size) {
|
||||||
|
typedef typename remove_cv<shared_ptr<T>::element_type>::type T1;
|
||||||
|
T1* p1 = 0;
|
||||||
|
detail::allocate_array_helper<A, T1> a1(allocator, size, &p1);
|
||||||
|
detail::array_deleter<T1> d1;
|
||||||
|
shared_ptr<T> s1(p1, d1, a1);
|
||||||
|
detail::array_deleter<T1>* d2;
|
||||||
|
d2 = get_deleter<detail::array_deleter<T1> >(s1);
|
||||||
|
d2->construct(p1, size);
|
||||||
|
return shared_ptr<T>(s1, p1);
|
||||||
|
}
|
||||||
|
#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS)
|
||||||
|
template<typename T, typename A, typename... Args>
|
||||||
|
inline typename detail::sp_if_array<T>::type
|
||||||
|
allocate_shared(const A& allocator, size_t size, Args&&... args) {
|
||||||
|
typedef typename remove_cv<shared_ptr<T>::element_type>::type T1;
|
||||||
|
T1* p1 = 0;
|
||||||
|
detail::allocate_array_helper<A, T1> a1(allocator, size, &p1);
|
||||||
|
detail::array_deleter<T1> d1;
|
||||||
|
shared_ptr<T> s1(p1, d1, a1);
|
||||||
|
detail::array_deleter<T1>* d2;
|
||||||
|
d2 = get_deleter<detail::array_deleter<T1> >(s1);
|
||||||
|
d2->construct(p1, size, std::forward<Args>(args)...);
|
||||||
|
return shared_ptr<T>(s1, p1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
99
include/boost/smart_ptr/detail/allocate_array_helper.hpp
Normal file
99
include/boost/smart_ptr/detail/allocate_array_helper.hpp
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012 Glen Joseph Fernandes
|
||||||
|
* glenfe at live dot com
|
||||||
|
*
|
||||||
|
* Distributed under the Boost Software License,
|
||||||
|
* Version 1.0. (See accompanying file LICENSE_1_0.txt
|
||||||
|
* or copy at http://boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
#ifndef BOOST_SMART_PTR_DETAIL_ALLOCATE_ARRAY_HELPER_HPP
|
||||||
|
#define BOOST_SMART_PTR_DETAIL_ALLOCATE_ARRAY_HELPER_HPP
|
||||||
|
|
||||||
|
#include <boost/type_traits/alignment_of.hpp>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace detail {
|
||||||
|
template<typename A, typename T, typename Y = T>
|
||||||
|
class allocate_array_helper {
|
||||||
|
template<typename A, typename T, typename Y>
|
||||||
|
friend class allocate_array_helper;
|
||||||
|
typedef typename A::rebind<Y> ::other A2;
|
||||||
|
typedef typename A::rebind<char>::other A3;
|
||||||
|
public:
|
||||||
|
typedef typename A2::value_type value_type;
|
||||||
|
typedef typename A2::pointer pointer;
|
||||||
|
typedef typename A2::const_pointer const_pointer;
|
||||||
|
typedef typename A2::reference reference;
|
||||||
|
typedef typename A2::const_reference const_reference;
|
||||||
|
typedef typename A2::size_type size_type;
|
||||||
|
typedef typename A2::difference_type difference_type;
|
||||||
|
template<typename U>
|
||||||
|
struct rebind {
|
||||||
|
typedef allocate_array_helper<A, T, U> other;
|
||||||
|
};
|
||||||
|
allocate_array_helper(const A& allocator, std::size_t size, T** data)
|
||||||
|
: allocator(allocator),
|
||||||
|
size(sizeof(T) * size),
|
||||||
|
data(data) {
|
||||||
|
}
|
||||||
|
allocate_array_helper(const allocate_array_helper& other)
|
||||||
|
: allocator(other.allocator),
|
||||||
|
size(other.size),
|
||||||
|
data(other.data) {
|
||||||
|
}
|
||||||
|
template<class U>
|
||||||
|
allocate_array_helper(const allocate_array_helper<A, T, U>& other)
|
||||||
|
: allocator(other.allocator),
|
||||||
|
size(other.size),
|
||||||
|
data(other.data) {
|
||||||
|
}
|
||||||
|
pointer address(reference value) const {
|
||||||
|
return allocator.address(value);
|
||||||
|
}
|
||||||
|
const_pointer address(const_reference value) const {
|
||||||
|
return allocator.address(value);
|
||||||
|
}
|
||||||
|
size_type max_size() const {
|
||||||
|
return allocator.max_size();
|
||||||
|
}
|
||||||
|
pointer allocate(size_type count, const void* value = 0) {
|
||||||
|
std::size_t a1 = alignment_of<T>::value;
|
||||||
|
std::size_t n1 = count * sizeof(Y) + a1 - 1;
|
||||||
|
char* p1 = A3(allocator).allocate(n1 + size, value);
|
||||||
|
char* p2 = p1 + n1;
|
||||||
|
while (std::size_t(p2) % a1 != 0) {
|
||||||
|
p2--;
|
||||||
|
}
|
||||||
|
*data = reinterpret_cast<T*>(p2);
|
||||||
|
return reinterpret_cast<Y*>(p1);
|
||||||
|
}
|
||||||
|
void deallocate(pointer memory, size_type count) {
|
||||||
|
std::size_t a1 = alignment_of<T>::value;
|
||||||
|
std::size_t n1 = count * sizeof(Y) + a1 - 1;
|
||||||
|
char* p1 = reinterpret_cast<char*>(memory);
|
||||||
|
A3(allocator).deallocate(p1, n1 + size);
|
||||||
|
}
|
||||||
|
void construct(pointer memory, const Y& value) {
|
||||||
|
allocator.construct(memory, value);
|
||||||
|
}
|
||||||
|
void destroy(pointer memory) {
|
||||||
|
allocator.destroy(memory);
|
||||||
|
}
|
||||||
|
template<typename U>
|
||||||
|
bool operator==(const allocate_array_helper<A, T, U>& other) const {
|
||||||
|
return allocator == other.allocator;
|
||||||
|
}
|
||||||
|
template<typename U>
|
||||||
|
bool operator!=(const allocate_array_helper<A, T, U>& other) const {
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
A2 allocator;
|
||||||
|
std::size_t size;
|
||||||
|
T** data;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
62
include/boost/smart_ptr/detail/array_deleter.hpp
Normal file
62
include/boost/smart_ptr/detail/array_deleter.hpp
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012 Glen Joseph Fernandes
|
||||||
|
* glenfe at live dot com
|
||||||
|
*
|
||||||
|
* Distributed under the Boost Software License,
|
||||||
|
* Version 1.0. (See accompanying file LICENSE_1_0.txt
|
||||||
|
* or copy at http://boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_DELETER_HPP
|
||||||
|
#define BOOST_SMART_PTR_DETAIL_ARRAY_DELETER_HPP
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace detail {
|
||||||
|
template<typename T>
|
||||||
|
class array_deleter {
|
||||||
|
public:
|
||||||
|
array_deleter()
|
||||||
|
: size(0) {
|
||||||
|
}
|
||||||
|
~array_deleter() {
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
void construct(T* memory, std::size_t count) {
|
||||||
|
for (object = memory; size < count; size++) {
|
||||||
|
void* p1 = object + size;
|
||||||
|
::new(p1) T();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS)
|
||||||
|
template<typename... Args>
|
||||||
|
void construct(T* memory, std::size_t count, Args&&... args) {
|
||||||
|
for (object = memory; size < count; size++) {
|
||||||
|
void* p1 = object + size;
|
||||||
|
::new(p1) T(args...);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
void construct_noinit(T* memory, std::size_t count) {
|
||||||
|
for (object = memory; size < count; size++) {
|
||||||
|
void* p1 = object + size;
|
||||||
|
::new(p1) T;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void operator()(T*) {
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
void destroy() {
|
||||||
|
while (size > 0) {
|
||||||
|
object[--size].~T();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::size_t size;
|
||||||
|
T* object;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
92
include/boost/smart_ptr/detail/make_array_helper.hpp
Normal file
92
include/boost/smart_ptr/detail/make_array_helper.hpp
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012 Glen Joseph Fernandes
|
||||||
|
* glenfe at live dot com
|
||||||
|
*
|
||||||
|
* Distributed under the Boost Software License,
|
||||||
|
* Version 1.0. (See accompanying file LICENSE_1_0.txt
|
||||||
|
* or copy at http://boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
#ifndef BOOST_SMART_PTR_DETAIL_MAKE_ARRAY_HELPER_HPP
|
||||||
|
#define BOOST_SMART_PTR_DETAIL_MAKE_ARRAY_HELPER_HPP
|
||||||
|
|
||||||
|
#include <boost/type_traits/alignment_of.hpp>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace detail {
|
||||||
|
template<typename T, typename Y = T>
|
||||||
|
class make_array_helper {
|
||||||
|
template<typename T, typename Y>
|
||||||
|
friend class make_array_helper;
|
||||||
|
public:
|
||||||
|
typedef typename Y value_type;
|
||||||
|
typedef typename Y* pointer;
|
||||||
|
typedef typename const Y* const_pointer;
|
||||||
|
typedef typename Y& reference;
|
||||||
|
typedef typename const Y& const_reference;
|
||||||
|
typedef typename std::size_t size_type;
|
||||||
|
typedef typename ptrdiff_t difference_type;
|
||||||
|
template<typename U>
|
||||||
|
struct rebind {
|
||||||
|
typedef make_array_helper<T, U> other;
|
||||||
|
};
|
||||||
|
make_array_helper(std::size_t size, T** data)
|
||||||
|
: size(sizeof(T) * size),
|
||||||
|
data(data) {
|
||||||
|
}
|
||||||
|
make_array_helper(const make_array_helper& other)
|
||||||
|
: size(other.size),
|
||||||
|
data(other.data) {
|
||||||
|
}
|
||||||
|
template<class U>
|
||||||
|
make_array_helper(const make_array_helper<T, U>& other)
|
||||||
|
: size(other.size),
|
||||||
|
data(other.data) {
|
||||||
|
}
|
||||||
|
pointer address(reference value) const {
|
||||||
|
return &value;
|
||||||
|
}
|
||||||
|
const_pointer address(const_reference value) const {
|
||||||
|
return &value;
|
||||||
|
}
|
||||||
|
size_type max_size() const {
|
||||||
|
return static_cast<std::size_t>(-1) / sizeof(Y);
|
||||||
|
}
|
||||||
|
pointer allocate(size_type count, const void* = 0) {
|
||||||
|
std::size_t a1 = alignment_of<T>::value;
|
||||||
|
std::size_t n1 = count * sizeof(Y) + a1 - 1;
|
||||||
|
void* p1 = ::operator new(n1 + size);
|
||||||
|
char* p2 = static_cast<char*>(p1) + n1;
|
||||||
|
while (std::size_t(p2) % a1 != 0) {
|
||||||
|
p2--;
|
||||||
|
}
|
||||||
|
*data = reinterpret_cast<T*>(p2);
|
||||||
|
return reinterpret_cast<Y*>(p1);
|
||||||
|
}
|
||||||
|
void deallocate(pointer memory, size_type) {
|
||||||
|
void* p1 = memory;
|
||||||
|
::operator delete(p1);
|
||||||
|
}
|
||||||
|
void construct(pointer memory, const Y& value) {
|
||||||
|
void* p1 = memory;
|
||||||
|
::new(p1) Y(value);
|
||||||
|
}
|
||||||
|
void destroy(pointer memory) {
|
||||||
|
memory->~Y();
|
||||||
|
}
|
||||||
|
template<typename U>
|
||||||
|
bool operator==(const make_array_helper<T, U>& other) const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
template<typename U>
|
||||||
|
bool operator!=(const make_array_helper<T, U>& other) const {
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
std::size_t size;
|
||||||
|
T** data;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
28
include/boost/smart_ptr/detail/sp_if_array.hpp
Normal file
28
include/boost/smart_ptr/detail/sp_if_array.hpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012 Glen Joseph Fernandes
|
||||||
|
* glenfe at live dot com
|
||||||
|
*
|
||||||
|
* Distributed under the Boost Software License,
|
||||||
|
* Version 1.0. (See accompanying file LICENSE_1_0.txt
|
||||||
|
* or copy at http://boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
#ifndef BOOST_SMART_PTR_DETAIL_SP_IF_ARRAY_HPP
|
||||||
|
#define BOOST_SMART_PTR_DETAIL_SP_IF_ARRAY_HPP
|
||||||
|
|
||||||
|
#include <boost/smart_ptr/shared_ptr.hpp>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace detail {
|
||||||
|
template<typename T>
|
||||||
|
struct sp_if_array {
|
||||||
|
};
|
||||||
|
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||||
|
template<typename T>
|
||||||
|
struct sp_if_array<T[]> {
|
||||||
|
typedef boost::shared_ptr<T[]> type;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
62
include/boost/smart_ptr/make_shared_array.hpp
Normal file
62
include/boost/smart_ptr/make_shared_array.hpp
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012 Glen Joseph Fernandes
|
||||||
|
* glenfe at live dot com
|
||||||
|
*
|
||||||
|
* Distributed under the Boost Software License,
|
||||||
|
* Version 1.0. (See accompanying file LICENSE_1_0.txt
|
||||||
|
* or copy at http://boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
#ifndef BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP
|
||||||
|
#define BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP
|
||||||
|
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <boost/smart_ptr/detail/array_deleter.hpp>
|
||||||
|
#include <boost/smart_ptr/detail/make_array_helper.hpp>
|
||||||
|
#include <boost/smart_ptr/detail/sp_if_array.hpp>
|
||||||
|
#include <boost/type_traits/remove_cv.hpp>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
template<typename T>
|
||||||
|
inline typename detail::sp_if_array<T>::type
|
||||||
|
make_shared(std::size_t size) {
|
||||||
|
typedef typename remove_cv<shared_ptr<T>::element_type>::type T1;
|
||||||
|
T1* p1 = 0;
|
||||||
|
detail::make_array_helper<T1> a1(size, &p1);
|
||||||
|
detail::array_deleter<T1> d1;
|
||||||
|
shared_ptr<T> s1(p1, d1, a1);
|
||||||
|
detail::array_deleter<T1>* d2;
|
||||||
|
d2 = get_deleter<detail::array_deleter<T1> >(s1);
|
||||||
|
d2->construct(p1, size);
|
||||||
|
return shared_ptr<T>(s1, p1);
|
||||||
|
}
|
||||||
|
#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS)
|
||||||
|
template<typename T, typename... Args>
|
||||||
|
inline typename detail::sp_if_array<T>::type
|
||||||
|
make_shared(std::size_t size, Args&&... args) {
|
||||||
|
typedef typename remove_cv<shared_ptr<T>::element_type>::type T1;
|
||||||
|
T1* p1 = 0;
|
||||||
|
detail::make_array_helper<T1> a1(size, &p1);
|
||||||
|
detail::array_deleter<T1> d1;
|
||||||
|
shared_ptr<T> s1(p1, d1, a1);
|
||||||
|
detail::array_deleter<T1>* d2;
|
||||||
|
d2 = get_deleter<detail::array_deleter<T1> >(s1);
|
||||||
|
d2->construct(p1, size, std::forward<Args>(args)...);
|
||||||
|
return shared_ptr<T>(s1, p1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
template<typename T>
|
||||||
|
inline typename detail::sp_if_array<T>::type
|
||||||
|
make_shared_noinit(std::size_t size) {
|
||||||
|
typedef typename remove_cv<shared_ptr<T>::element_type>::type T1;
|
||||||
|
T1* p1 = 0;
|
||||||
|
detail::make_array_helper<T1> a1(size, &p1);
|
||||||
|
detail::array_deleter<T1> d1;
|
||||||
|
shared_ptr<T> s1(p1, d1, a1);
|
||||||
|
detail::array_deleter<T1>* d2;
|
||||||
|
d2 = get_deleter<detail::array_deleter<T1> >(s1);
|
||||||
|
d2->construct_noinit(p1, size);
|
||||||
|
return shared_ptr<T>(s1, p1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
100
make_shared_array.html
Normal file
100
make_shared_array.html
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>make_shared and allocate_shared</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
</head>
|
||||||
|
<body text="#000000" bgColor="#ffffff" link="#0000ff" vlink="#0000ff">
|
||||||
|
<h1><IMG height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
|
||||||
|
width="277" align="middle" border="0">make_shared and allocate_shared
|
||||||
|
for arrays</h1>
|
||||||
|
<p><A href="#Introduction">Introduction</A><br>
|
||||||
|
<A href="#Synopsis">Synopsis</A><br>
|
||||||
|
<A href="#functions">Free Functions</A><br>
|
||||||
|
<A href="#example">Example</A><br>
|
||||||
|
<h2><a name="Introduction">Introduction</a></h2>
|
||||||
|
<p>One criticism of Boost <a href="shared_array.htm">shared_array</a> is
|
||||||
|
the lack of utility similar to <a href="make_shared.htm">make_shared</a>
|
||||||
|
which ensures only a single allocation for an array. A second criticism
|
||||||
|
is Boost <code>shared_array</code> does not support custom allocators
|
||||||
|
and so also lacks an <code>allocate_shared</code> utility.</p>
|
||||||
|
<p>The header files <boost/smart_ptr/make_shared_array.hpp> and
|
||||||
|
<boost/smart_ptr/allocate_shared_array.hpp> provide new function
|
||||||
|
templates, <code>make_shared</code> and <code>allocate_shared</code>,
|
||||||
|
to address this need. <code>make_shared</code> uses the global
|
||||||
|
operator <code>new</code> to allocate memory, whereas
|
||||||
|
<code>allocate_shared</code> uses an user-supplied allocator,
|
||||||
|
allowing finer control.</p>
|
||||||
|
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||||
|
<pre>namespace boost {
|
||||||
|
template<typename T>
|
||||||
|
shared_ptr<T> <a href="#functions">make_shared</a>(size_t size);
|
||||||
|
|
||||||
|
template<typename T, typename A>
|
||||||
|
shared_ptr<T> <a href="#functions">allocate_shared</a>(const A& allocator, size_t size);
|
||||||
|
|
||||||
|
#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS)
|
||||||
|
template<typename T, typename... Args>
|
||||||
|
shared_ptr<T> <a href="#functions">make_shared</a>(size_t size, Args&&... args);
|
||||||
|
|
||||||
|
template<typename T, typename A, typename... Args>
|
||||||
|
shared_ptr<T> <a href="#functions">allocate_shared</a>(const A& allocator, size_t size, Args&&... args);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
shared_ptr<T> <a href="#functions">make_shared_noinit</a>(size_t size);
|
||||||
|
}</pre>
|
||||||
|
<h2><a name="functions">Free Functions</a></h2>
|
||||||
|
<pre>template<typename T, typename... Args>
|
||||||
|
shared_ptr<T> make_shared(size_t size, Args&&... args);
|
||||||
|
template<typename T, typename A, typename... Args>
|
||||||
|
shared_ptr<T> allocate_shared(const A& allocator, size_t size, Args&&... args);</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Requires:</b> The expression
|
||||||
|
<code>new(pointer) T(std::forward<Args>(args)...)</code>, where
|
||||||
|
<code>pointer</code> is a <code>void*</code> pointing to storage
|
||||||
|
suitable to hold an object of type <code>T</code>, shall be
|
||||||
|
well-formed. <code>A</code> shall be an <em>Allocator</em>, as
|
||||||
|
described in section 20.1.5 (<strong>Allocator requirements</strong>)
|
||||||
|
of the C++ Standard. The copy constructor and destructor of
|
||||||
|
<code>A</code> shall not throw.</p>
|
||||||
|
<p><b>Effects:</b> Allocates memory suitable for an array of type
|
||||||
|
<code>T</code> and size <code>size</code> and constructs an array
|
||||||
|
of objects in it via the placement new expression
|
||||||
|
<code>new(pointer) T()</code> or
|
||||||
|
<code>new(pointer) T(std::forward<Args>(args)...)</code>.
|
||||||
|
<code>allocate_shared</code> uses a copy of
|
||||||
|
<code>allocator</code> to allocate memory. If an exception is thrown,
|
||||||
|
has no effect.</p>
|
||||||
|
<p><b>Returns:</b> A <code>shared_ptr</code> instance that stores and
|
||||||
|
owns the address of the newly constructed array of type <code>T</code>
|
||||||
|
and size <code>size</code>.</p>
|
||||||
|
<p><b>Postconditions:</b>
|
||||||
|
<code>get() != 0 && use_count() == 1</code>.</p>
|
||||||
|
<p><b>Throws:</b> <code>bad_alloc</code>, or an exception thrown from
|
||||||
|
<code>A::allocate</code> or the constructor of <code>T</code>.</p>
|
||||||
|
<p><b>Notes:</b> This implementation allocates the memory required for
|
||||||
|
the returned <code>shared_ptr</code> and an array of type
|
||||||
|
<code>T</code> of size <code>size</code> in a single allocation. This
|
||||||
|
provides efficiency to equivalent to an intrusive smart array
|
||||||
|
pointer.</p>
|
||||||
|
<p>The prototypes shown above are used if your compiler supports r-value
|
||||||
|
references and variadic templates. They perfectly forward the
|
||||||
|
<code>args</code> parameters to the constructors of
|
||||||
|
<code>T</code> for each array element.</p>
|
||||||
|
<p>Otherwise, you can use the overloads which take only the array size
|
||||||
|
(and the allocator in case of <code>allocate_shared</code>) and do not
|
||||||
|
take any constructor arguments. These overloads invoke the default
|
||||||
|
constructor of <code>T</code> for each array element.</p>
|
||||||
|
</blockquote>
|
||||||
|
<h2><a name="example">Example</a></h2>
|
||||||
|
<pre>boost::shared_ptr<int[]> array = boost::make_shared<int[]>(size);</pre>
|
||||||
|
<hr>
|
||||||
|
<p>$Date: 2012-10-30 10:12:25 -0800 (Tue, 30 Oct 2012) $</p>
|
||||||
|
<p><small>Copyright 2012 Glen Fernandes. Distributed under the Boost
|
||||||
|
Software License, Version 1.0. See accompanying file
|
||||||
|
<A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or copy at
|
||||||
|
<A href="http://www.boost.org/LICENSE_1_0.txt">
|
||||||
|
http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
42
test/allocate_shared_array_esft_test.cpp
Normal file
42
test/allocate_shared_array_esft_test.cpp
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012 Glen Joseph Fernandes
|
||||||
|
* glenfe at live dot com
|
||||||
|
*
|
||||||
|
* Distributed under the Boost Software License,
|
||||||
|
* Version 1.0. (See accompanying file LICENSE_1_0.txt
|
||||||
|
* or copy at http://boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
#include <boost/detail/lightweight_test.hpp>
|
||||||
|
#include <boost/smart_ptr/allocate_shared_array.hpp>
|
||||||
|
#include <boost/smart_ptr/enable_shared_from_this.hpp>
|
||||||
|
|
||||||
|
class type
|
||||||
|
: public boost::enable_shared_from_this<type> {
|
||||||
|
public:
|
||||||
|
static unsigned int instances;
|
||||||
|
explicit type() {
|
||||||
|
instances++;
|
||||||
|
}
|
||||||
|
~type() {
|
||||||
|
instances--;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
type(const type&);
|
||||||
|
type& operator=(const type&);
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned int type::instances = 0;
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
BOOST_TEST(type::instances == 0);
|
||||||
|
{
|
||||||
|
boost::shared_ptr<type[]> a1 = boost::allocate_shared<type[]>(std::allocator<type>(), 3);
|
||||||
|
try {
|
||||||
|
a1[0].shared_from_this();
|
||||||
|
BOOST_ERROR("shared_from_this did not throw");
|
||||||
|
} catch (const boost::bad_weak_ptr&) {
|
||||||
|
BOOST_TEST(type::instances == 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return boost::report_errors();
|
||||||
|
}
|
87
test/allocate_shared_array_test.cpp
Normal file
87
test/allocate_shared_array_test.cpp
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012 Glen Joseph Fernandes
|
||||||
|
* glenfe at live dot com
|
||||||
|
*
|
||||||
|
* Distributed under the Boost Software License,
|
||||||
|
* Version 1.0. (See accompanying file LICENSE_1_0.txt
|
||||||
|
* or copy at http://boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
#include <boost/detail/lightweight_test.hpp>
|
||||||
|
#include <boost/smart_ptr/allocate_shared_array.hpp>
|
||||||
|
#include <boost/smart_ptr/weak_ptr.hpp>
|
||||||
|
#include <boost/type_traits/alignment_of.hpp>
|
||||||
|
|
||||||
|
class type {
|
||||||
|
public:
|
||||||
|
static unsigned int instances;
|
||||||
|
explicit type(int = 0, int = 0)
|
||||||
|
: member() {
|
||||||
|
instances++;
|
||||||
|
}
|
||||||
|
~type() {
|
||||||
|
instances--;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
type(const type&);
|
||||||
|
type& operator=(const type&);
|
||||||
|
double member;
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned int type::instances = 0;
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
{
|
||||||
|
boost::shared_ptr<int[]> a1 = boost::allocate_shared<int[]>(std::allocator<int>(), 3);
|
||||||
|
int* a2 = a1.get();
|
||||||
|
BOOST_TEST(a1.use_count() == 1);
|
||||||
|
BOOST_TEST(a2 != 0);
|
||||||
|
BOOST_TEST(size_t(a2) % boost::alignment_of<int>::value == 0);
|
||||||
|
BOOST_TEST(a1[0] == 0);
|
||||||
|
BOOST_TEST(a1[1] == 0);
|
||||||
|
BOOST_TEST(a1[2] == 0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
boost::shared_ptr<const int[]> a1 = boost::allocate_shared<const int[]>(std::allocator<int>(), 3);
|
||||||
|
const int* a2 = a1.get();
|
||||||
|
BOOST_TEST(a1.use_count() == 1);
|
||||||
|
BOOST_TEST(a2 != 0);
|
||||||
|
BOOST_TEST(size_t(a2) % boost::alignment_of<int>::value == 0);
|
||||||
|
BOOST_TEST(a1[0] == 0);
|
||||||
|
BOOST_TEST(a1[1] == 0);
|
||||||
|
BOOST_TEST(a1[2] == 0);
|
||||||
|
}
|
||||||
|
BOOST_TEST(type::instances == 0);
|
||||||
|
{
|
||||||
|
boost::shared_ptr<type[]> a1 = boost::allocate_shared<type[]>(std::allocator<type>(), 3);
|
||||||
|
type* a2 = a1.get();
|
||||||
|
BOOST_TEST(a1.use_count() == 1);
|
||||||
|
BOOST_TEST(a2 != 0);
|
||||||
|
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
|
||||||
|
BOOST_TEST(type::instances == 3);
|
||||||
|
boost::weak_ptr<type[]> w1 = a1;
|
||||||
|
a1.reset();
|
||||||
|
BOOST_TEST(type::instances == 0);
|
||||||
|
}
|
||||||
|
BOOST_TEST(type::instances == 0);
|
||||||
|
{
|
||||||
|
boost::shared_ptr<const type[]> a1 = boost::allocate_shared<const type[]>(std::allocator<type>(), 3);
|
||||||
|
const type* a2 = a1.get();
|
||||||
|
BOOST_TEST(a1.use_count() == 1);
|
||||||
|
BOOST_TEST(a2 != 0);
|
||||||
|
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
|
||||||
|
BOOST_TEST(type::instances == 3);
|
||||||
|
}
|
||||||
|
#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS)
|
||||||
|
BOOST_TEST(type::instances == 0);
|
||||||
|
{
|
||||||
|
boost::shared_ptr<type[]> a1 = boost::allocate_shared<type[]>(std::allocator<type>(), 3, 1, 5);
|
||||||
|
type* a2 = a1.get();
|
||||||
|
BOOST_TEST(type::instances == 3);
|
||||||
|
BOOST_TEST(a2 != 0);
|
||||||
|
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
|
||||||
|
a1.reset();
|
||||||
|
BOOST_TEST(type::instances == 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return boost::report_errors();
|
||||||
|
}
|
40
test/allocate_shared_array_throws_test.cpp
Normal file
40
test/allocate_shared_array_throws_test.cpp
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012 Glen Joseph Fernandes
|
||||||
|
* glenfe at live dot com
|
||||||
|
*
|
||||||
|
* Distributed under the Boost Software License,
|
||||||
|
* Version 1.0. (See accompanying file LICENSE_1_0.txt
|
||||||
|
* or copy at http://boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
#include <boost/detail/lightweight_test.hpp>
|
||||||
|
#include <boost/smart_ptr/allocate_shared_array.hpp>
|
||||||
|
|
||||||
|
class type {
|
||||||
|
public:
|
||||||
|
static unsigned int instances;
|
||||||
|
explicit type() {
|
||||||
|
if (instances == 5) {
|
||||||
|
throw true;
|
||||||
|
}
|
||||||
|
instances++;
|
||||||
|
}
|
||||||
|
~type() {
|
||||||
|
instances--;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
type(const type&);
|
||||||
|
type& operator=(const type&);
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned int type::instances = 0;
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
BOOST_TEST(type::instances == 0);
|
||||||
|
try {
|
||||||
|
boost::allocate_shared<type[]>(std::allocator<type>(), 6);
|
||||||
|
BOOST_ERROR("allocate_shared did not throw");
|
||||||
|
} catch (...) {
|
||||||
|
BOOST_TEST(type::instances == 0);
|
||||||
|
}
|
||||||
|
return boost::report_errors();
|
||||||
|
}
|
52
test/make_shared_array_esft_test.cpp
Normal file
52
test/make_shared_array_esft_test.cpp
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012 Glen Joseph Fernandes
|
||||||
|
* glenfe at live dot com
|
||||||
|
*
|
||||||
|
* Distributed under the Boost Software License,
|
||||||
|
* Version 1.0. (See accompanying file LICENSE_1_0.txt
|
||||||
|
* or copy at http://boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
#include <boost/detail/lightweight_test.hpp>
|
||||||
|
#include <boost/smart_ptr/enable_shared_from_this.hpp>
|
||||||
|
#include <boost/smart_ptr/make_shared_array.hpp>
|
||||||
|
|
||||||
|
class type
|
||||||
|
: public boost::enable_shared_from_this<type> {
|
||||||
|
public:
|
||||||
|
static unsigned int instances;
|
||||||
|
explicit type() {
|
||||||
|
instances++;
|
||||||
|
}
|
||||||
|
~type() {
|
||||||
|
instances--;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
type(const type&);
|
||||||
|
type& operator=(const type&);
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned int type::instances = 0;
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
BOOST_TEST(type::instances == 0);
|
||||||
|
{
|
||||||
|
boost::shared_ptr<type[]> a1 = boost::make_shared<type[]>(3);
|
||||||
|
try {
|
||||||
|
a1[0].shared_from_this();
|
||||||
|
BOOST_ERROR("shared_from_this did not throw");
|
||||||
|
} catch (const boost::bad_weak_ptr&) {
|
||||||
|
BOOST_TEST(type::instances == 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BOOST_TEST(type::instances == 0);
|
||||||
|
{
|
||||||
|
boost::shared_ptr<type[]> a1 = boost::make_shared_noinit<type[]>(3);
|
||||||
|
try {
|
||||||
|
a1[0].shared_from_this();
|
||||||
|
BOOST_ERROR("shared_from_this did not throw");
|
||||||
|
} catch (const boost::bad_weak_ptr&) {
|
||||||
|
BOOST_TEST(type::instances == 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return boost::report_errors();
|
||||||
|
}
|
118
test/make_shared_array_test.cpp
Normal file
118
test/make_shared_array_test.cpp
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012 Glen Joseph Fernandes
|
||||||
|
* glenfe at live dot com
|
||||||
|
*
|
||||||
|
* Distributed under the Boost Software License,
|
||||||
|
* Version 1.0. (See accompanying file LICENSE_1_0.txt
|
||||||
|
* or copy at http://boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
#include <boost/detail/lightweight_test.hpp>
|
||||||
|
#include <boost/smart_ptr/make_shared_array.hpp>
|
||||||
|
#include <boost/smart_ptr/weak_ptr.hpp>
|
||||||
|
#include <boost/type_traits/alignment_of.hpp>
|
||||||
|
|
||||||
|
class type {
|
||||||
|
public:
|
||||||
|
static unsigned int instances;
|
||||||
|
explicit type(int = 0, int = 0)
|
||||||
|
: member() {
|
||||||
|
instances++;
|
||||||
|
}
|
||||||
|
~type() {
|
||||||
|
instances--;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
type(const type&);
|
||||||
|
type& operator=(const type&);
|
||||||
|
double member;
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned int type::instances = 0;
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
{
|
||||||
|
boost::shared_ptr<int[]> a1 = boost::make_shared<int[]>(3);
|
||||||
|
int* a2 = a1.get();
|
||||||
|
BOOST_TEST(a1.use_count() == 1);
|
||||||
|
BOOST_TEST(a2 != 0);
|
||||||
|
BOOST_TEST(size_t(a2) % boost::alignment_of<int>::value == 0);
|
||||||
|
BOOST_TEST(a1[0] == 0);
|
||||||
|
BOOST_TEST(a1[1] == 0);
|
||||||
|
BOOST_TEST(a1[2] == 0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
boost::shared_ptr<const int[]> a1 = boost::make_shared<const int[]>(3);
|
||||||
|
const int* a2 = a1.get();
|
||||||
|
BOOST_TEST(a1.use_count() == 1);
|
||||||
|
BOOST_TEST(a2 != 0);
|
||||||
|
BOOST_TEST(size_t(a2) % boost::alignment_of<int>::value == 0);
|
||||||
|
BOOST_TEST(a1[0] == 0);
|
||||||
|
BOOST_TEST(a1[1] == 0);
|
||||||
|
BOOST_TEST(a1[2] == 0);
|
||||||
|
}
|
||||||
|
BOOST_TEST(type::instances == 0);
|
||||||
|
{
|
||||||
|
boost::shared_ptr<type[]> a1 = boost::make_shared<type[]>(3);
|
||||||
|
type* a2 = a1.get();
|
||||||
|
BOOST_TEST(a1.use_count() == 1);
|
||||||
|
BOOST_TEST(a2 != 0);
|
||||||
|
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
|
||||||
|
BOOST_TEST(type::instances == 3);
|
||||||
|
boost::weak_ptr<type[]> w1 = a1;
|
||||||
|
a1.reset();
|
||||||
|
BOOST_TEST(type::instances == 0);
|
||||||
|
}
|
||||||
|
BOOST_TEST(type::instances == 0);
|
||||||
|
{
|
||||||
|
boost::shared_ptr<const type[]> a1 = boost::make_shared<const type[]>(3);
|
||||||
|
const type* a2 = a1.get();
|
||||||
|
BOOST_TEST(a1.use_count() == 1);
|
||||||
|
BOOST_TEST(a2 != 0);
|
||||||
|
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
|
||||||
|
BOOST_TEST(type::instances == 3);
|
||||||
|
}
|
||||||
|
#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS)
|
||||||
|
BOOST_TEST(type::instances == 0);
|
||||||
|
{
|
||||||
|
boost::shared_ptr<type[]> a1 = boost::make_shared<type[]>(3, 1, 5);
|
||||||
|
type* a2 = a1.get();
|
||||||
|
BOOST_TEST(type::instances == 3);
|
||||||
|
BOOST_TEST(a2 != 0);
|
||||||
|
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
|
||||||
|
a1.reset();
|
||||||
|
BOOST_TEST(type::instances == 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
boost::shared_ptr<int[]> a1 = boost::make_shared_noinit<int[]>(3);
|
||||||
|
int* a2 = a1.get();
|
||||||
|
BOOST_TEST(a2 != 0);
|
||||||
|
BOOST_TEST(size_t(a2) % boost::alignment_of<int>::value == 0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
boost::shared_ptr<const int[]> a1 = boost::make_shared_noinit<const int[]>(3);
|
||||||
|
const int* a2 = a1.get();
|
||||||
|
BOOST_TEST(a2 != 0);
|
||||||
|
BOOST_TEST(size_t(a2) % boost::alignment_of<int>::value == 0);
|
||||||
|
}
|
||||||
|
BOOST_TEST(type::instances == 0);
|
||||||
|
{
|
||||||
|
boost::shared_ptr<type[]> a1 = boost::make_shared_noinit<type[]>(3);
|
||||||
|
type* a2 = a1.get();
|
||||||
|
BOOST_TEST(a2 != 0);
|
||||||
|
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
|
||||||
|
BOOST_TEST(type::instances == 3);
|
||||||
|
boost::weak_ptr<type[]> w1 = a1;
|
||||||
|
a1.reset();
|
||||||
|
BOOST_TEST(type::instances == 0);
|
||||||
|
}
|
||||||
|
BOOST_TEST(type::instances == 0);
|
||||||
|
{
|
||||||
|
boost::shared_ptr<const type[]> a1 = boost::make_shared_noinit<const type[]>(3);
|
||||||
|
const type* a2 = a1.get();
|
||||||
|
BOOST_TEST(a2 != 0);
|
||||||
|
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
|
||||||
|
BOOST_TEST(type::instances == 3);
|
||||||
|
}
|
||||||
|
return boost::report_errors();
|
||||||
|
}
|
47
test/make_shared_array_throws_test.cpp
Normal file
47
test/make_shared_array_throws_test.cpp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012 Glen Joseph Fernandes
|
||||||
|
* glenfe at live dot com
|
||||||
|
*
|
||||||
|
* Distributed under the Boost Software License,
|
||||||
|
* Version 1.0. (See accompanying file LICENSE_1_0.txt
|
||||||
|
* or copy at http://boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
#include <boost/detail/lightweight_test.hpp>
|
||||||
|
#include <boost/smart_ptr/make_shared_array.hpp>
|
||||||
|
|
||||||
|
class type {
|
||||||
|
public:
|
||||||
|
static unsigned int instances;
|
||||||
|
explicit type() {
|
||||||
|
if (instances == 5) {
|
||||||
|
throw true;
|
||||||
|
}
|
||||||
|
instances++;
|
||||||
|
}
|
||||||
|
~type() {
|
||||||
|
instances--;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
type(const type&);
|
||||||
|
type& operator=(const type&);
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned int type::instances = 0;
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
BOOST_TEST(type::instances == 0);
|
||||||
|
try {
|
||||||
|
boost::make_shared<type[]>(6);
|
||||||
|
BOOST_ERROR("make_shared did not throw");
|
||||||
|
} catch (...) {
|
||||||
|
BOOST_TEST(type::instances == 0);
|
||||||
|
}
|
||||||
|
BOOST_TEST(type::instances == 0);
|
||||||
|
try {
|
||||||
|
boost::shared_ptr<type[]> a1 = boost::make_shared_noinit<type[]>(6);
|
||||||
|
BOOST_ERROR("make_shared_noinit did not throw");
|
||||||
|
} catch (...) {
|
||||||
|
BOOST_TEST(type::instances == 0);
|
||||||
|
}
|
||||||
|
return boost::report_errors();
|
||||||
|
}
|
Reference in New Issue
Block a user