forked from boostorg/core
Implement noinit_allocator_adaptor
This commit is contained in:
@ -50,6 +50,7 @@ criteria for inclusion is that the utility component be:
|
|||||||
[include is_same.qbk]
|
[include is_same.qbk]
|
||||||
[include lightweight_test.qbk]
|
[include lightweight_test.qbk]
|
||||||
[include no_exceptions_support.qbk]
|
[include no_exceptions_support.qbk]
|
||||||
|
[include noinit_adaptor.qbk]
|
||||||
[include noncopyable.qbk]
|
[include noncopyable.qbk]
|
||||||
[include null_deleter.qbk]
|
[include null_deleter.qbk]
|
||||||
[include pointer_traits.qbk]
|
[include pointer_traits.qbk]
|
||||||
|
141
doc/noinit_adaptor.qbk
Normal file
141
doc/noinit_adaptor.qbk
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
[/
|
||||||
|
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)
|
||||||
|
]
|
||||||
|
|
||||||
|
[section:noinit_adaptor noinit_adaptor]
|
||||||
|
|
||||||
|
[simplesect Authors]
|
||||||
|
|
||||||
|
* Glen Fernandes
|
||||||
|
|
||||||
|
[endsimplesect]
|
||||||
|
|
||||||
|
[section Overview]
|
||||||
|
|
||||||
|
The header <boost/core/noinit_adaptor.hpp> provides the class
|
||||||
|
template `boost::noinit_adaptor` that converts any allocator into
|
||||||
|
one whose `construct(ptr)` performs default initialization via placement new,
|
||||||
|
and whose `destroy(ptr)` invokes `value_type` destructor directly.
|
||||||
|
|
||||||
|
[endsect]
|
||||||
|
|
||||||
|
[section Example]
|
||||||
|
|
||||||
|
The following example shows use of this allocator adaptor to achieve default
|
||||||
|
initialization of elements of a trivial type, which are later assigned values.
|
||||||
|
|
||||||
|
```
|
||||||
|
#include <boost/core/noinit_adaptor.hpp>
|
||||||
|
#include <numeric>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::vector<int,
|
||||||
|
boost::noinit_adaptor<std::allocator<int> > > v(5);
|
||||||
|
std::iota(v.begin(), v.end(), 1);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
[endsect]
|
||||||
|
|
||||||
|
[section Reference]
|
||||||
|
|
||||||
|
```
|
||||||
|
namespace boost {
|
||||||
|
|
||||||
|
template<class A>
|
||||||
|
struct noinit_adaptor
|
||||||
|
: A {
|
||||||
|
template<class U>
|
||||||
|
struct rebind {
|
||||||
|
typedef noinit_adaptor<typename std::allocator_traits<A>::template
|
||||||
|
rebind_alloc<U> > other;
|
||||||
|
};
|
||||||
|
|
||||||
|
noinit_adaptor() noexcept;
|
||||||
|
|
||||||
|
template<class U>
|
||||||
|
noinit_adaptor(U&& u) noexcept;
|
||||||
|
|
||||||
|
template<class U>
|
||||||
|
noinit_adaptor(const noinit_adaptor<U>& u) noexcept;
|
||||||
|
|
||||||
|
template<class U>
|
||||||
|
void construct(U* p);
|
||||||
|
|
||||||
|
template<class U, class V, class... Args>
|
||||||
|
void construct(U* p, V&& v, Args&&... args);
|
||||||
|
|
||||||
|
template<class U>
|
||||||
|
void destroy(U* p);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T, class U>
|
||||||
|
bool operator==(const noinit_adaptor<T>& lhs,
|
||||||
|
const noinit_adaptor<U>& rhs) noexcept;
|
||||||
|
|
||||||
|
template<class T, class U>
|
||||||
|
bool operator!=(const noinit_adaptor<T>& lhs,
|
||||||
|
const noinit_adaptor<U>& rhs) noexcept;
|
||||||
|
|
||||||
|
} /* boost */
|
||||||
|
```
|
||||||
|
|
||||||
|
[section Constructors]
|
||||||
|
|
||||||
|
[variablelist
|
||||||
|
[[`noinit_adaptor() noexcept;`]
|
||||||
|
[[variablelist
|
||||||
|
[[Effects][Value initializes the A base class.]]]]]
|
||||||
|
[[`template<class U> noinit_adaptor(U&& u) noexcept;`]
|
||||||
|
[[variablelist
|
||||||
|
[[Requires][`A` shall be constructible from `U`.]]
|
||||||
|
[[Effects][Initializes the `A` base class with `std::forward<U>(u)`.]]]]]
|
||||||
|
[[`template<class U> noinit_adaptor(const noinit_adaptor<U>& u) noexcept;`]
|
||||||
|
[[variablelist
|
||||||
|
[[Requires][`A` shall be constructible from `U`.]]
|
||||||
|
[[Effects][Initializes the `A` base class with
|
||||||
|
`static_cast<const U&>(u)`.]]]]]]
|
||||||
|
|
||||||
|
[endsect]
|
||||||
|
|
||||||
|
[section Member functions]
|
||||||
|
|
||||||
|
[variablelist
|
||||||
|
[[`template<class U> void construct(U* p);`]
|
||||||
|
[[variablelist
|
||||||
|
[[Effects][`::new((void*)p) U`.]]]]]
|
||||||
|
[[`template<class U, class V, class... Args> void construct(U* p, V&& v,
|
||||||
|
Args&&... args);`]
|
||||||
|
[[variablelist
|
||||||
|
[[Effects][`::new(void*)p) U(std::forward<V>(v),
|
||||||
|
std::forward<Args>(args)...)`.]]]]]
|
||||||
|
[[`template<class U> void destroy(U* p);`]
|
||||||
|
[[variablelist
|
||||||
|
[[Effects][`p->~U()`.]]]]]]
|
||||||
|
|
||||||
|
[endsect]
|
||||||
|
|
||||||
|
[section Operators]
|
||||||
|
|
||||||
|
[variablelist
|
||||||
|
[[`template<class T, class U> constexpr bool
|
||||||
|
operator==(const noinit_adaptor<T>& lhs,
|
||||||
|
const noinit_adaptor<U>& rhs) noexcept;`]
|
||||||
|
[[variablelist
|
||||||
|
[[Returns][`static_cast<const T&>(lhs) == static_cast<const U&>(rhs)`.]]]]]
|
||||||
|
[[`template<class T, class U> constexpr bool
|
||||||
|
operator!=(const noinit_adaptor<T>& lhs,
|
||||||
|
const noinit_adaptor<U>& rhs) noexcept;`]
|
||||||
|
[[variablelist
|
||||||
|
[[Returns][`!(lhs == rhs)`.]]]]]]
|
||||||
|
|
||||||
|
[endsect]
|
||||||
|
|
||||||
|
[endsect]
|
||||||
|
|
||||||
|
[endsect]
|
96
include/boost/core/noinit_adaptor.hpp
Normal file
96
include/boost/core/noinit_adaptor.hpp
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
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_CORE_NOINIT_ADAPTOR_HPP
|
||||||
|
#define BOOST_CORE_NOINIT_ADAPTOR_HPP
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#include <memory>
|
||||||
|
#include <new>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
|
||||||
|
template<class A>
|
||||||
|
struct noinit_adaptor
|
||||||
|
: A {
|
||||||
|
template<class U>
|
||||||
|
struct rebind {
|
||||||
|
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
|
||||||
|
typedef noinit_adaptor<typename std::allocator_traits<A>::template
|
||||||
|
rebind_alloc<U> > other;
|
||||||
|
#else
|
||||||
|
typedef noinit_adaptor<typename A::template rebind<U>::other> other;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
noinit_adaptor()
|
||||||
|
: A() { }
|
||||||
|
|
||||||
|
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||||
|
template<class U>
|
||||||
|
noinit_adaptor(U&& u) BOOST_NOEXCEPT
|
||||||
|
: A(std::forward<U>(u)) { }
|
||||||
|
#else
|
||||||
|
template<class U>
|
||||||
|
noinit_adaptor(const U& u) BOOST_NOEXCEPT
|
||||||
|
: A(u) { }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<class U>
|
||||||
|
noinit_adaptor(const noinit_adaptor<U>& u) BOOST_NOEXCEPT
|
||||||
|
: A(static_cast<const U&>(u)) { }
|
||||||
|
|
||||||
|
template<class U>
|
||||||
|
void construct(U* p) {
|
||||||
|
::new((void*)p) U;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||||
|
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||||
|
template<class U, class V, class... Args>
|
||||||
|
void construct(U* p, V&& v, Args&&... args) {
|
||||||
|
::new((void*)p) U(std::forward<V>(v), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
template<class U, class V>
|
||||||
|
void construct(U* p, V&& v) {
|
||||||
|
::new((void*)p) U(std::forward<V>(v));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
template<class U, class V>
|
||||||
|
void construct(U* p, const V& v) {
|
||||||
|
::new((void*)p) U(v);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<class U>
|
||||||
|
void destroy(U* p) {
|
||||||
|
p->~U();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T, class U>
|
||||||
|
inline bool
|
||||||
|
operator==(const noinit_adaptor<T>& lhs,
|
||||||
|
const noinit_adaptor<U>& rhs) BOOST_NOEXCEPT
|
||||||
|
{
|
||||||
|
return static_cast<const T&>(lhs) == static_cast<const U&>(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class U>
|
||||||
|
inline bool
|
||||||
|
operator!=(const noinit_adaptor<T>& lhs,
|
||||||
|
const noinit_adaptor<U>& rhs) BOOST_NOEXCEPT
|
||||||
|
{
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* boost */
|
||||||
|
|
||||||
|
#endif
|
@ -137,6 +137,7 @@ run-fail quick_exit_fail.cpp ;
|
|||||||
compile use_default_test.cpp ;
|
compile use_default_test.cpp ;
|
||||||
|
|
||||||
run default_allocator_test.cpp ;
|
run default_allocator_test.cpp ;
|
||||||
|
run noinit_adaptor_test.cpp ;
|
||||||
|
|
||||||
lib lib_typeid : lib_typeid.cpp : <link>shared:<define>LIB_TYPEID_DYN_LINK=1 ;
|
lib lib_typeid : lib_typeid.cpp : <link>shared:<define>LIB_TYPEID_DYN_LINK=1 ;
|
||||||
|
|
||||||
|
107
test/noinit_adaptor_test.cpp
Normal file
107
test/noinit_adaptor_test.cpp
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
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 <boost/core/default_allocator.hpp>
|
||||||
|
#include <boost/core/noinit_adaptor.hpp>
|
||||||
|
#include <boost/core/lightweight_test.hpp>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class creator
|
||||||
|
: public boost::default_allocator<T> {
|
||||||
|
public:
|
||||||
|
template<class U>
|
||||||
|
struct rebind {
|
||||||
|
typedef creator<U> other;
|
||||||
|
};
|
||||||
|
|
||||||
|
creator(int* count)
|
||||||
|
: count_(count) { }
|
||||||
|
|
||||||
|
template<class U>
|
||||||
|
creator(const creator<U>& other)
|
||||||
|
: count_(other.count()) { }
|
||||||
|
|
||||||
|
template<class U, class V>
|
||||||
|
void construct(U*, const V&) {
|
||||||
|
++(*count_);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class U>
|
||||||
|
void destroy(U*) {
|
||||||
|
--(*count_);
|
||||||
|
}
|
||||||
|
|
||||||
|
int* count() const {
|
||||||
|
return count_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int* count_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T, class U>
|
||||||
|
inline bool
|
||||||
|
operator==(const creator<T>& lhs, const creator<U>& rhs)
|
||||||
|
{
|
||||||
|
return lhs.count() == rhs.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class U>
|
||||||
|
inline bool
|
||||||
|
operator!=(const creator<T>& lhs, const creator<U>& rhs)
|
||||||
|
{
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
class type {
|
||||||
|
public:
|
||||||
|
type() { }
|
||||||
|
|
||||||
|
type(int value)
|
||||||
|
: value_(value) { }
|
||||||
|
|
||||||
|
int value() const {
|
||||||
|
return value_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int value_;
|
||||||
|
};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
int c = 0;
|
||||||
|
std::vector<int, boost::noinit_adaptor<creator<int> > > v(&c);
|
||||||
|
BOOST_TEST(c == 0);
|
||||||
|
v.push_back(1);
|
||||||
|
BOOST_TEST(v.front() == 1);
|
||||||
|
v.push_back(2);
|
||||||
|
BOOST_TEST(c == 0);
|
||||||
|
v.clear();
|
||||||
|
BOOST_TEST(c == 0);
|
||||||
|
v.resize(5);
|
||||||
|
BOOST_TEST(c == 0);
|
||||||
|
v.front() = 1;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
int c = 0;
|
||||||
|
std::vector<type, boost::noinit_adaptor<creator<type> > > v(&c);
|
||||||
|
BOOST_TEST(c == 0);
|
||||||
|
v.push_back(1);
|
||||||
|
BOOST_TEST(v.front().value() == 1);
|
||||||
|
v.push_back(2);
|
||||||
|
BOOST_TEST(c == 0);
|
||||||
|
v.clear();
|
||||||
|
BOOST_TEST(c == 0);
|
||||||
|
v.resize(5);
|
||||||
|
BOOST_TEST(c == 0);
|
||||||
|
v.front() = 1;
|
||||||
|
}
|
||||||
|
return boost::report_errors();
|
||||||
|
}
|
Reference in New Issue
Block a user