libcruft-util/iterator/placement_output.hpp

59 lines
1.7 KiB
C++

/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright 2021, Danny Robson <danny@nerdcruft.net>
*/
#pragma once
#include <iterator>
#include <type_traits>
#include <utility>
///////////////////////////////////////////////////////////////////////////////
namespace cruft::iterator {
/// An output iterator that calls placement new on a supplied pointer
/// during assignment.
///
/// This simplifies usage of uninitialised arrays with STL algorithms.
template <typename PointerT>
struct placement_output {
public:
static_assert (std::is_pointer_v<PointerT>);
using iterator_category = std::output_iterator_tag;
using value_type = void;
using difference_type = void;
using pointer = void;
using reference = void;
placement_output (PointerT _cursor)
: m_cursor (_cursor)
{ ; }
placement_output& operator++ () { ++m_cursor; return *this; }
placement_output& operator * () { return *this; }
placement_output& operator-> () { return this; }
template <typename ValueT>
placement_output&
operator= (ValueT &&val)
{
new (m_cursor) bare_type (std::forward<ValueT> (val));
return *this;
}
private:
using bare_type = std::remove_pointer_t<PointerT>;
PointerT m_cursor;
};
template <typename PointerT>
placement_output (PointerT) -> placement_output<std::remove_reference_t<PointerT>>;
}