doc: shared_array
This commit is contained in:
+14
-7
@@ -120,9 +120,16 @@ Array fields
|
||||
------------
|
||||
|
||||
Array fields are represented with the `pvxs::shared_array` container
|
||||
using void vs. non-void, and const vs. non-const element types.
|
||||
using void vs. non-void, and const vs. mutable element types.
|
||||
|
||||
Arrays are initially created as non-const and non-void.
|
||||
.. code-block:: c++
|
||||
|
||||
shared_array<uint32_t> typed_mutable;
|
||||
shared_array<const uint32_t> typed_const;
|
||||
shared_array<void> void_mutable;
|
||||
shared_array<const void> void_const;
|
||||
|
||||
Arrays may be initially created as mutable and non-void.
|
||||
After being populated, an array must be transformed using
|
||||
`pvxs::shared_array::freeze` to become const before
|
||||
being stored in a `pvxs::Value`.
|
||||
@@ -133,8 +140,8 @@ being stored in a `pvxs::Value`.
|
||||
Value top = nt::NTScalar{TypeCode::Float64A}.create();
|
||||
|
||||
top["value"] = arr.freeze();
|
||||
# freeze() acts like std::move(). arr is now empty
|
||||
# only the read-only reference remains!
|
||||
// freeze() acts like std::move(). arr is now empty
|
||||
// only the read-only reference remains!
|
||||
|
||||
The `pvxs::shared_array::freeze` method is special in that it
|
||||
acts like std::move() in that it moves the array reference into the returned object.
|
||||
@@ -146,7 +153,7 @@ The const non-void option is a convenience which may **allocate** and do an elem
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
# extract reference, or converted copy
|
||||
// extract reference, or converted copy
|
||||
arr = top["value"].as<shared_array<const double>>();
|
||||
|
||||
When it is desirable to avoid an implicit allocate and convert,
|
||||
@@ -156,10 +163,10 @@ of the underlying array prior to using `pvxs::shared_array::castTo`.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
# extract untyped reference. Never copies
|
||||
// extract untyped reference. Never copies
|
||||
shared_array<const void> varr = top["value"].as<shared_array<const void>>();
|
||||
if(varr.original_type()==ArrayType::Float64) {
|
||||
# castTo() throws std::logic_error if the underlying type is not 'double'.
|
||||
// castTo() throws std::logic_error if the underlying type is not 'double'.
|
||||
shared_array<const double> temp = varr.castTo<const double>();
|
||||
}
|
||||
|
||||
|
||||
+77
-13
@@ -209,6 +209,8 @@ shared_array<void> copyAs(ArrayType dtype, ArrayType stype, const void *sbase, s
|
||||
} // namespace detail
|
||||
|
||||
/** std::vector-like contiguous array of items passed by reference.
|
||||
*
|
||||
* Somewhat analogous to ``std::shared_ptr<std::vector<T>>``.
|
||||
*
|
||||
* shared_array comes in const and non-const, as well as void and non-void variants.
|
||||
*
|
||||
@@ -257,9 +259,18 @@ public:
|
||||
|
||||
typedef E element_type;
|
||||
|
||||
//! Pointer to no array.
|
||||
//! @post size()==0
|
||||
constexpr shared_array() noexcept :base_t() {}
|
||||
|
||||
//! allocate new array and populate from initializer list
|
||||
/** Allocate new array and populate from initializer list.
|
||||
*
|
||||
* @code
|
||||
* shared_array<uint32> arr({1,2,3});
|
||||
* @endcode
|
||||
*
|
||||
* @post size()==L.size()
|
||||
*/
|
||||
template<typename A>
|
||||
shared_array(std::initializer_list<A> L)
|
||||
:base_t(new _E_non_const[L.size()], L.size())
|
||||
@@ -268,8 +279,16 @@ public:
|
||||
std::copy(L.begin(), L.end(), raw);
|
||||
}
|
||||
|
||||
//! Construct a copy of another a sequence.
|
||||
//! Requires random access iterators.
|
||||
/** Construct a copy of a sequence or range of random access iterators.
|
||||
*
|
||||
* @code
|
||||
* special_vectorish<uint32_t> X(...);
|
||||
* shared_array<uint32_t> Y(X.begin(), X.end());
|
||||
*
|
||||
* uint32_t cvals[] = {1,2,3,4};
|
||||
* shared_array<uint32_t> Z(cvals, cvals + NELEMENTS(cvals));
|
||||
* @endcode
|
||||
*/
|
||||
template<typename Iter, typename std::iterator_traits<Iter>::difference_type=0>
|
||||
shared_array(Iter begin, Iter end)
|
||||
:shared_array(std::distance(begin, end))
|
||||
@@ -277,12 +296,12 @@ public:
|
||||
std::copy(begin, end, const_cast<_E_non_const*>(this->begin()));
|
||||
}
|
||||
|
||||
//! @brief Allocate (with new[]) a new vector of size c
|
||||
//! Allocate (with new[]) a new vector of c elements, which are default constructed.
|
||||
explicit shared_array(size_t c)
|
||||
:base_t(new _E_non_const[c], c)
|
||||
{}
|
||||
|
||||
//! @brief Allocate (with new[]) a new vector of size c and fill with value e
|
||||
//! @brief Allocate (with new[]) a new vector of size c and fill with copies of e
|
||||
template<typename V>
|
||||
shared_array(size_t c, V e)
|
||||
:base_t(new _E_non_const[c], c)
|
||||
@@ -290,23 +309,54 @@ public:
|
||||
std::fill_n((_E_non_const*)this->_data.get(), this->_count, e);
|
||||
}
|
||||
|
||||
//! use existing alloc with delete[]
|
||||
/** Wrap existing alloc with delete[]
|
||||
*
|
||||
* @param a Array allocated with ``new E[len]``.
|
||||
* @param len Number of elements
|
||||
*/
|
||||
shared_array(E* a, size_t len)
|
||||
:base_t(a, len)
|
||||
{}
|
||||
|
||||
//! use existing alloc w/ custom deletor
|
||||
/** Wrap existing alloc w/ custom deletor
|
||||
*
|
||||
* @param a Array base pointer
|
||||
* @param b Deletor object. ``b(a)`` must be valid.
|
||||
* @param len Number of elements
|
||||
*/
|
||||
template<typename B>
|
||||
shared_array(E* a, B b, size_t len)
|
||||
:base_t(a, b, len)
|
||||
{}
|
||||
|
||||
//! build around existing shared_ptr
|
||||
/** Wrap around existing shared_ptr
|
||||
*
|
||||
* Argument shared_ptr will likely be creating using that class's aliasing constructor.
|
||||
*/
|
||||
shared_array(const std::shared_ptr<E>& a, size_t len)
|
||||
:base_t(a, len)
|
||||
{}
|
||||
|
||||
//! alias existing shared_array
|
||||
/** Alias existing shared_ptr
|
||||
*
|
||||
* A powerful tool for adapting external data containers to shared_array without copying.
|
||||
*
|
||||
* @param a Ownership object
|
||||
* @param b Base pointer. Must remain valid until ownership object is destructed.
|
||||
* @param len Number of elements
|
||||
*
|
||||
* @post data()==b
|
||||
*
|
||||
* @code
|
||||
* auto stdvec(std::make_shared<std::vector<uint32_t>>({1,2,3}));
|
||||
*
|
||||
* shared_array<uint32_t> aliasvec(stdvec, stdvec->data(), stdvec->size());
|
||||
*
|
||||
* stdvec.reset(); // release original reference
|
||||
*
|
||||
* aliasvec.reset(); // ~vector runs!
|
||||
* @endcode
|
||||
*/
|
||||
template<typename A>
|
||||
shared_array(const std::shared_ptr<A>& a, E* b, size_t len)
|
||||
:base_t(a, b, len)
|
||||
@@ -398,10 +448,24 @@ public:
|
||||
return (*this)[i];
|
||||
}
|
||||
|
||||
//! Cast to const, consuming this
|
||||
//! @pre unique()==true
|
||||
//! @post empty()==true
|
||||
//! @throws std::logic_error if !unique()
|
||||
/** Cast single mutable reference to const, consuming this
|
||||
*
|
||||
* Transfers reference from this object to the returned object.
|
||||
*
|
||||
* @pre unique()==true
|
||||
* @post empty()==true
|
||||
* @throws std::logic_error if !unique()
|
||||
*
|
||||
* @code
|
||||
* shared_array<uint32_t> mutator({1,2,3});
|
||||
* mutator[0] = 42;
|
||||
*
|
||||
* shared_array<const utin32_t> frozen(mutator.freeze());
|
||||
*
|
||||
* assert(mutator.empty()); // array reference transferred to 'frozen'
|
||||
* assert(frozen.size()==3);
|
||||
* @endcode
|
||||
*/
|
||||
shared_array<typename std::add_const<E>::type>
|
||||
freeze() {
|
||||
if(!this->unique())
|
||||
|
||||
Reference in New Issue
Block a user