hide appender_range definition
parent
c0421b721b
commit
b1f207bd3b
|
@ -123,7 +123,7 @@ int main() {
|
|||
writefln("%@s", Foo{});
|
||||
writefln("%@i", Foo{});
|
||||
|
||||
auto s = appender_range<std::string>{};
|
||||
auto s = appender<std::string>();
|
||||
/* formatting into a string sink (can be any output range, but
|
||||
* appender makes sure the capacity is unlimited so it's safe)
|
||||
*/
|
||||
|
|
|
@ -82,7 +82,7 @@ struct format_spec;
|
|||
*
|
||||
* Anything that writes into the output range will do. The output range is
|
||||
* exactly the same output range the outer format call is formatting into,
|
||||
* so for example when someone is formatting into an ostd::appender_range,
|
||||
* so for example when someone is formatting into an ostd::appender(),
|
||||
* it will be just that.
|
||||
*
|
||||
* This may be specialized in other libostd modules as well.
|
||||
|
|
158
ostd/range.hh
158
ostd/range.hh
|
@ -1535,93 +1535,91 @@ namespace detail {
|
|||
}, p_ranges);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct appender_range: output_range<appender_range<T>> {
|
||||
using value_type = typename T::value_type;
|
||||
|
||||
appender_range(): p_data() {}
|
||||
|
||||
appender_range(T const &v): p_data(v) {}
|
||||
appender_range(T &&v): p_data(std::move(v)) {}
|
||||
|
||||
appender_range &operator=(T const &v) {
|
||||
p_data = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
appender_range &operator=(T &&v) {
|
||||
p_data = std::move(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void clear() { p_data.clear(); }
|
||||
bool empty() const { return p_data.empty(); }
|
||||
|
||||
void reserve(typename T::size_type cap) { p_data.reserve(cap); }
|
||||
void resize(typename T::size_type len) { p_data.resize(len); }
|
||||
|
||||
typename T::size_type size() const { return p_data.size(); }
|
||||
typename T::size_type capacity() const { return p_data.capacity(); }
|
||||
|
||||
void put(typename T::const_reference v) {
|
||||
p_data.push_back(v);
|
||||
}
|
||||
|
||||
void put(typename T::value_type &&v) {
|
||||
p_data.push_back(std::move(v));
|
||||
}
|
||||
|
||||
T &get() { return p_data; }
|
||||
T const &get() const { return p_data; }
|
||||
|
||||
private:
|
||||
T p_data;
|
||||
};
|
||||
} /* namespace detail */
|
||||
|
||||
/** @brief An appender range is an output range over a standard container.
|
||||
/** @brief Creates am appender output range for a container.
|
||||
*
|
||||
* It will effectively `push_back(v)` into the container every time a `put(v)`
|
||||
* is called on the appender. It works with any container that implements the
|
||||
* `push_back(v)` method.
|
||||
* An appender is a kind of output range which wraps a standard container
|
||||
* that supports `push_back(v)` and appends to it on every `put(v)`. The
|
||||
* value type of the range is the value type of the container.
|
||||
*
|
||||
* It also implements some methods to manipulate the container itself which
|
||||
* are not part of the output range interface. Not all of them might work,
|
||||
* depending on the container stored.
|
||||
* It's posssible to assign a new container to it by copy or move, as long
|
||||
* as the container is of the same type. It's also possible to create a new
|
||||
* appender from an existing container by copy or move, using
|
||||
* ostd::appender(Container &&).
|
||||
*
|
||||
* Besides implementing a standard output range, appenders also implement
|
||||
* an interface to the container, particularly the `clear()`, `empty()`,
|
||||
* `reserve(capacity)`, `resize(length)`, `size()` and `capacity()` methods.
|
||||
* These are available depending on if they're also available in the wrapped
|
||||
* container and have identical signatures.
|
||||
*
|
||||
* The `get()` method returns a reference to the wrapped container.
|
||||
* The `put(v)` method is overloaded for both by-copy and by-move put.
|
||||
*
|
||||
* @see ostd::appender(Container &&)
|
||||
*/
|
||||
template<typename T>
|
||||
struct appender_range: output_range<appender_range<T>> {
|
||||
using value_type = typename T::value_type;
|
||||
|
||||
/** @brief Default constructs the container inside. */
|
||||
appender_range(): p_data() {}
|
||||
|
||||
/** @brief Constructs from a copy of a container. */
|
||||
appender_range(T const &v): p_data(v) {}
|
||||
|
||||
/** @brief Constructs an appender by moving a container into it. */
|
||||
appender_range(T &&v): p_data(std::move(v)) {}
|
||||
|
||||
/** @brief Assigns a copy of a container to the appender. */
|
||||
appender_range &operator=(T const &v) {
|
||||
p_data = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** @brief Assigns a container to the appender by move. */
|
||||
appender_range &operator=(T &&v) {
|
||||
p_data = std::move(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** @brief Clears the underlying container's contents. */
|
||||
void clear() { p_data.clear(); }
|
||||
|
||||
/** @brief Checks if the underlying container is empty. */
|
||||
bool empty() const { return p_data.empty(); }
|
||||
|
||||
/** @brief Reserves some capacity in the container. */
|
||||
void reserve(typename T::size_type cap) { p_data.reserve(cap); }
|
||||
|
||||
/** @brief Resizes the container. */
|
||||
void resize(typename T::size_type len) { p_data.resize(len); }
|
||||
|
||||
/** @brief Gets the container size. */
|
||||
typename T::size_type size() const { return p_data.size(); }
|
||||
|
||||
/** @brief Gets the container capacity. */
|
||||
typename T::size_type capacity() const { return p_data.capacity(); }
|
||||
|
||||
/** @brief Appends a copy of a value to the end of the container. */
|
||||
void put(typename T::const_reference v) {
|
||||
p_data.push_back(v);
|
||||
}
|
||||
|
||||
/** @brief Appends a value to the end of the container by move */
|
||||
void put(typename T::value_type &&v) {
|
||||
p_data.push_back(std::move(v));
|
||||
}
|
||||
|
||||
/** @brief Gets a reference to the underlying container. */
|
||||
T &get() { return p_data; }
|
||||
private:
|
||||
T p_data;
|
||||
};
|
||||
|
||||
/** @brief A convenience method to create an appender. */
|
||||
template<typename T>
|
||||
inline appender_range<T> appender() {
|
||||
return appender_range<T>();
|
||||
template<typename Container>
|
||||
inline auto appender() {
|
||||
return detail::appender_range<Container>();
|
||||
}
|
||||
|
||||
/** @brief A convenience method to create an appender. */
|
||||
template<typename T>
|
||||
inline appender_range<T> appender(T const &v) {
|
||||
return appender_range<T>(v);
|
||||
}
|
||||
|
||||
/** @brief A convenience method to create an appender. */
|
||||
template<typename T>
|
||||
inline appender_range<T> appender(T &&v) {
|
||||
return appender_range<T>(std::forward<T>(v));
|
||||
/** @brief Creates an appender from an existing container.
|
||||
*
|
||||
* Like ostd::appender(), except uses an existing container to create the
|
||||
* range. The container is passed by universal reference, so it will work
|
||||
* for lvalues and rvalues and appropriately copy or move the container.
|
||||
*
|
||||
* @see ostd::appender()
|
||||
*/
|
||||
template<typename Container>
|
||||
inline auto appender(Container &&v) {
|
||||
return detail::appender_range<
|
||||
std::remove_cv_t<std::remove_reference_t<Container>>
|
||||
>(std::forward<Container>(v));
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
|
|
@ -660,7 +660,7 @@ inline stream_range<T> stream::iter() {
|
|||
* it's an std::basic_string over `T`.
|
||||
*
|
||||
* @tparam T The type used for individual characters.
|
||||
* @tparam TC The type used to hold the line (in an ostd::appender_range).
|
||||
* @tparam TC The type used to hold the line (in an ostd::appender()).
|
||||
*
|
||||
* @see stream_range
|
||||
*/
|
||||
|
@ -755,7 +755,7 @@ struct stream_line_range: input_range<stream_line_range<T, TC>> {
|
|||
|
||||
private:
|
||||
stream *p_stream;
|
||||
mutable appender_range<TC> p_item;
|
||||
mutable decltype(appender<TC>()) p_item;
|
||||
mutable bool p_has_item;
|
||||
bool p_keep_nl;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue