hide appender_range definition
parent
c0421b721b
commit
b1f207bd3b
|
@ -123,7 +123,7 @@ int main() {
|
||||||
writefln("%@s", Foo{});
|
writefln("%@s", Foo{});
|
||||||
writefln("%@i", 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
|
/* formatting into a string sink (can be any output range, but
|
||||||
* appender makes sure the capacity is unlimited so it's safe)
|
* 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
|
* 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,
|
* 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.
|
* it will be just that.
|
||||||
*
|
*
|
||||||
* This may be specialized in other libostd modules as well.
|
* 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);
|
}, 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 */
|
} /* 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)`
|
* An appender is a kind of output range which wraps a standard container
|
||||||
* is called on the appender. It works with any container that implements the
|
* that supports `push_back(v)` and appends to it on every `put(v)`. The
|
||||||
* `push_back(v)` method.
|
* value type of the range is the value type of the container.
|
||||||
*
|
*
|
||||||
* It also implements some methods to manipulate the container itself which
|
* It's posssible to assign a new container to it by copy or move, as long
|
||||||
* are not part of the output range interface. Not all of them might work,
|
* as the container is of the same type. It's also possible to create a new
|
||||||
* depending on the container stored.
|
* 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>
|
template<typename Container>
|
||||||
struct appender_range: output_range<appender_range<T>> {
|
inline auto appender() {
|
||||||
using value_type = typename T::value_type;
|
return detail::appender_range<Container>();
|
||||||
|
|
||||||
/** @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>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief A convenience method to create an appender. */
|
/** @brief Creates an appender from an existing container.
|
||||||
template<typename T>
|
*
|
||||||
inline appender_range<T> appender(T const &v) {
|
* Like ostd::appender(), except uses an existing container to create the
|
||||||
return appender_range<T>(v);
|
* range. The container is passed by universal reference, so it will work
|
||||||
}
|
* for lvalues and rvalues and appropriately copy or move the container.
|
||||||
|
*
|
||||||
/** @brief A convenience method to create an appender. */
|
* @see ostd::appender()
|
||||||
template<typename T>
|
*/
|
||||||
inline appender_range<T> appender(T &&v) {
|
template<typename Container>
|
||||||
return appender_range<T>(std::forward<T>(v));
|
inline auto appender(Container &&v) {
|
||||||
|
return detail::appender_range<
|
||||||
|
std::remove_cv_t<std::remove_reference_t<Container>>
|
||||||
|
>(std::forward<Container>(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
|
@ -660,7 +660,7 @@ inline stream_range<T> stream::iter() {
|
||||||
* it's an std::basic_string over `T`.
|
* it's an std::basic_string over `T`.
|
||||||
*
|
*
|
||||||
* @tparam T The type used for individual characters.
|
* @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
|
* @see stream_range
|
||||||
*/
|
*/
|
||||||
|
@ -755,7 +755,7 @@ struct stream_line_range: input_range<stream_line_range<T, TC>> {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
stream *p_stream;
|
stream *p_stream;
|
||||||
mutable appender_range<TC> p_item;
|
mutable decltype(appender<TC>()) p_item;
|
||||||
mutable bool p_has_item;
|
mutable bool p_has_item;
|
||||||
bool p_keep_nl;
|
bool p_keep_nl;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue