1
0
forked from boostorg/core

Implement noinit_allocator_adaptor

This commit is contained in:
Glen Fernandes
2019-04-27 19:14:10 -04:00
parent 62fff4d829
commit 50491408b1
5 changed files with 346 additions and 0 deletions

View File

@ -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
View 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]

View 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

View File

@ -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 ;

View 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();
}