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 lightweight_test.qbk]
|
||||
[include no_exceptions_support.qbk]
|
||||
[include noinit_adaptor.qbk]
|
||||
[include noncopyable.qbk]
|
||||
[include null_deleter.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 ;
|
||||
|
||||
run default_allocator_test.cpp ;
|
||||
run noinit_adaptor_test.cpp ;
|
||||
|
||||
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