forked from OctaForge/libostd
remove make_ range helpers for containers (use iter_begin/end)
This commit is contained in:
parent
ef147c538c
commit
cc8452e265
|
@ -1,9 +1,9 @@
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <clocale>
|
#include <clocale>
|
||||||
|
|
||||||
#include <ostd/algorithm.hh>
|
#include <ostd/algorithm.hh>
|
||||||
#include <ostd/vector.hh>
|
|
||||||
#include <ostd/unordered_map.hh>
|
|
||||||
#include <ostd/range.hh>
|
#include <ostd/range.hh>
|
||||||
#include <ostd/io.hh>
|
#include <ostd/io.hh>
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <ostd/range.hh>
|
#include <ostd/range.hh>
|
||||||
#include <ostd/io.hh>
|
#include <ostd/io.hh>
|
||||||
#include <ostd/algorithm.hh>
|
#include <ostd/algorithm.hh>
|
||||||
#include <ostd/vector.hh>
|
|
||||||
|
|
||||||
using namespace ostd;
|
using namespace ostd;
|
||||||
|
|
||||||
|
@ -27,7 +28,8 @@ int main() {
|
||||||
|
|
||||||
/* prints ABCDEF (ASCII 65, 66, 67, 68, 69, 70) */
|
/* prints ABCDEF (ASCII 65, 66, 67, 68, 69, 70) */
|
||||||
writeln("string gen test");
|
writeln("string gen test");
|
||||||
auto s = make_string(map(range(6), [](int v) -> char { return v + 65; }));
|
auto mr = map(range(6), [](int v) -> char { return v + 65; });
|
||||||
|
std::string s{mr.iter_begin(), mr.iter_end()};
|
||||||
writeln(s);
|
writeln(s);
|
||||||
|
|
||||||
/* join a few ranges together - prints 11, 22, 33 ... 99 each on new line */
|
/* join a few ranges together - prints 11, 22, 33 ... 99 each on new line */
|
||||||
|
|
|
@ -23,7 +23,8 @@ int main() {
|
||||||
|
|
||||||
/* prints ABCDEF (ASCII 65, 66, 67, 68, 69, 70) */
|
/* prints ABCDEF (ASCII 65, 66, 67, 68, 69, 70) */
|
||||||
writeln("string gen test");
|
writeln("string gen test");
|
||||||
auto s = make_string(range(6) | map([](int v) -> char { return v + 65; }));
|
auto mr = range(6) | map([](int v) -> char { return v + 65; });
|
||||||
|
std::string s{mr.iter_begin(), mr.iter_end()};
|
||||||
writeln(s);
|
writeln(s);
|
||||||
|
|
||||||
/* join a few ranges together - prints 11, 22, 33 ... 99 each on new line */
|
/* join a few ranges together - prints 11, 22, 33 ... 99 each on new line */
|
||||||
|
@ -76,15 +77,15 @@ int main() {
|
||||||
| filter([](auto v) { return v >= 65 && v <= 90; })
|
| filter([](auto v) { return v >= 65 && v <= 90; })
|
||||||
| map ([](auto v) { return char(v); });
|
| map ([](auto v) { return char(v); });
|
||||||
|
|
||||||
writeln(make_string(r));
|
writeln(std::string{r.iter_begin(), r.iter_end()});
|
||||||
|
|
||||||
/* "list comprehensions" */
|
/* "list comprehensions" */
|
||||||
writeln("list initialization");
|
writeln("list initialization");
|
||||||
|
|
||||||
auto test = make_vector(
|
auto vr = range(20)
|
||||||
range(20)
|
|
||||||
| filter([](int v) { return v % 2 == 0; })
|
| filter([](int v) { return v % 2 == 0; })
|
||||||
| map ([](int v) { return v * 2; })
|
| map ([](int v) { return v * 2; });
|
||||||
);
|
|
||||||
|
std::vector<int> test{vr.iter_begin(), vr.iter_end()};
|
||||||
writeln(test);
|
writeln(test);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <ostd/algorithm.hh>
|
#include <ostd/algorithm.hh>
|
||||||
#include <ostd/string.hh>
|
#include <ostd/string.hh>
|
||||||
#include <ostd/vector.hh>
|
|
||||||
#include <ostd/io.hh>
|
#include <ostd/io.hh>
|
||||||
|
|
||||||
using namespace ostd;
|
using namespace ostd;
|
||||||
|
@ -25,15 +26,21 @@ int main() {
|
||||||
|
|
||||||
writeln("## WHOLE FILE READ ##\n");
|
writeln("## WHOLE FILE READ ##\n");
|
||||||
|
|
||||||
auto ts1 = make_string(test.iter());
|
auto fr = test.iter();
|
||||||
writefln("-- str beg --\n%s-- str end --", ts1);
|
writefln(
|
||||||
|
"-- str beg --\n%s-- str end --",
|
||||||
|
std::string{fr.iter_begin(), fr.iter_end()}
|
||||||
|
);
|
||||||
|
|
||||||
test.seek(0);
|
test.seek(0);
|
||||||
|
|
||||||
writeln("\n## PART FILE READ ##\n");
|
writeln("\n## PART FILE READ ##\n");
|
||||||
|
|
||||||
auto ts2 = make_string(test.iter().take(25));
|
auto fr2 = test.iter().take(25);
|
||||||
writefln("-- str beg --\n%s\n-- str end --", ts2);
|
writefln(
|
||||||
|
"-- str beg --\n%s\n-- str end --",
|
||||||
|
std::string{fr2.iter_begin(), fr2.iter_end()}
|
||||||
|
);
|
||||||
|
|
||||||
test.seek(0);
|
test.seek(0);
|
||||||
|
|
||||||
|
@ -64,7 +71,8 @@ int main() {
|
||||||
|
|
||||||
test.open("test.txt");
|
test.open("test.txt");
|
||||||
|
|
||||||
auto x = make_vector<std::string>(test.iter_lines());
|
auto lns = test.iter_lines();
|
||||||
|
std::vector<std::string> x{lns.iter_begin(), lns.iter_end()};
|
||||||
writeln("before sort: ", x);
|
writeln("before sort: ", x);
|
||||||
sort(iter(x));
|
sort(iter(x));
|
||||||
writeln("after sort: ", x);
|
writeln("after sort: ", x);
|
||||||
|
|
|
@ -53,9 +53,9 @@
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "ostd/range.hh"
|
#include "ostd/range.hh"
|
||||||
#include "ostd/vector.hh"
|
|
||||||
#include "ostd/algorithm.hh"
|
#include "ostd/algorithm.hh"
|
||||||
|
|
||||||
namespace ostd {
|
namespace ostd {
|
||||||
|
@ -618,46 +618,6 @@ struct ranged_traits<std::basic_string<T, TR, A> const> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @brief Creates a string out of any generic range type.
|
|
||||||
*
|
|
||||||
* The character type of the string must be explicitly specified here.
|
|
||||||
* You can also optionally specify the character traits used for the string.
|
|
||||||
*/
|
|
||||||
template<
|
|
||||||
typename T, typename TR = std::char_traits<T>,
|
|
||||||
typename A = std::allocator<T>, typename R
|
|
||||||
>
|
|
||||||
inline std::basic_string<T, TR, A> make_string(R range, A const &alloc = A{}) {
|
|
||||||
std::basic_string<T, TR, A> ret{alloc};
|
|
||||||
using C = range_category_t<R>;
|
|
||||||
if constexpr(std::is_convertible_v<C, contiguous_range_tag>) {
|
|
||||||
ret.reserve(range.size());
|
|
||||||
ret.insert(ret.end(), range.data(), range.data() + range.size());
|
|
||||||
} else {
|
|
||||||
for (; !range.empty(); range.pop_front()) {
|
|
||||||
ret.push_back(range.front());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @brief Creates a string out of any generic range type.
|
|
||||||
*
|
|
||||||
* The character type of the string is guessed from the range type itself.
|
|
||||||
* You can also optionally specify the character traits used for the string.
|
|
||||||
*/
|
|
||||||
template<
|
|
||||||
typename R, typename TR = std::char_traits<std::remove_cv_t<range_value_t<R>>>,
|
|
||||||
typename A = std::allocator<std::remove_cv_t<range_value_t<R>>>
|
|
||||||
>
|
|
||||||
inline std::basic_string<std::remove_cv_t<range_value_t<R>>, TR, A> make_string(
|
|
||||||
R range, A const &alloc = A{}
|
|
||||||
) {
|
|
||||||
return make_string<std::remove_cv_t<range_value_t<R>>, TR, A>(
|
|
||||||
std::move(range), alloc
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* string literals */
|
/* string literals */
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
|
@ -1,142 +0,0 @@
|
||||||
/** @addtogroup Containers
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** @file unordered_map.hh
|
|
||||||
*
|
|
||||||
* @brief Extensions for std::unordered_map.
|
|
||||||
*
|
|
||||||
* This file provides extensions for the standard std::unordered_map container.
|
|
||||||
*
|
|
||||||
* @copyright See COPYING.md in the project tree for further information.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef OSTD_UNORDERED_MAP_HH
|
|
||||||
#define OSTD_UNORDERED_MAP_HH
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
#include "ostd/range.hh"
|
|
||||||
|
|
||||||
namespace ostd {
|
|
||||||
|
|
||||||
/** @addtogroup Containers
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
template<typename T>
|
|
||||||
std::integral_constant<
|
|
||||||
bool, std::tuple_size<T>::value == 2
|
|
||||||
> tuple2_like_test(typename std::tuple_size<T>::type *);
|
|
||||||
|
|
||||||
template<typename>
|
|
||||||
std::false_type tuple2_like_test(...);
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
constexpr bool is_2tuple_like = decltype(tuple2_like_test<T>(0))::value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @brief Creates an unordered map using a range.
|
|
||||||
*
|
|
||||||
* The range's value type must be either an std::pair or an std::tuple
|
|
||||||
* with 2 elements, additionally the key and value types must be constructible
|
|
||||||
* using the tuple or pair's first and second element respectively.
|
|
||||||
*
|
|
||||||
* You need to manually specify the key and value types for this overload.
|
|
||||||
*
|
|
||||||
* @param[in] range The range.
|
|
||||||
* @param[in] bcount The initial bucket count.
|
|
||||||
* @param[in] hash The hash function.
|
|
||||||
* @param[in] kequal The key equality comparison function.
|
|
||||||
* @param[in] alloc The allocator.
|
|
||||||
*
|
|
||||||
* @tparam K The key type.
|
|
||||||
* @tparam V The value type.
|
|
||||||
*/
|
|
||||||
template<
|
|
||||||
typename K, typename T, typename H = std::hash<K>,
|
|
||||||
typename E = std::equal_to<K>,
|
|
||||||
typename A = std::allocator<std::pair<K const, T>>, typename R
|
|
||||||
>
|
|
||||||
inline std::unordered_map<K, T, H, E, A> make_unordered_map(
|
|
||||||
R range, std::size_t bcount = 1, H const &hash = H{},
|
|
||||||
E const &kequal = E{}, A const &alloc = A{}
|
|
||||||
) {
|
|
||||||
static_assert(
|
|
||||||
detail::is_2tuple_like<range_value_t<R>>,
|
|
||||||
"the range element must be a pair/2-tuple"
|
|
||||||
);
|
|
||||||
|
|
||||||
using MP = std::pair<K const, T>;
|
|
||||||
using AK = std::tuple_element_t<0, range_value_t<R>>;
|
|
||||||
using AV = std::tuple_element_t<1, range_value_t<R>>;
|
|
||||||
|
|
||||||
static_assert(
|
|
||||||
std::is_constructible_v<K const, AK> && std::is_constructible_v<T, AV>,
|
|
||||||
"incompatible range element type"
|
|
||||||
);
|
|
||||||
|
|
||||||
std::unordered_map<K, T, H, E, A> ret{bcount, hash, kequal, alloc};
|
|
||||||
|
|
||||||
using C = range_category_t<R>;
|
|
||||||
if constexpr(std::is_convertible_v<C, finite_random_access_range_tag>) {
|
|
||||||
/* at least try to preallocate here... */
|
|
||||||
ret.reserve(range.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; !range.empty(); range.pop_front()) {
|
|
||||||
if constexpr(std::is_constructible_v<MP, range_value_t<R>>) {
|
|
||||||
ret.emplace(range.front());
|
|
||||||
} else {
|
|
||||||
/* store a temporary to prevent calling front() twice; however,
|
|
||||||
* for values that can be used to construct the pair directly
|
|
||||||
* we can just do the above
|
|
||||||
*/
|
|
||||||
range_value_t<R> v{range.front()};
|
|
||||||
ret.emplace(std::move(std::get<0>(v)), std::move(std::get<1>(v)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @brief Creates an unordered map using a range.
|
|
||||||
*
|
|
||||||
* Calls into make_unordered_map() using the range value type's first and
|
|
||||||
* second element types as key and value respectively.
|
|
||||||
*/
|
|
||||||
template<
|
|
||||||
typename R,
|
|
||||||
typename H = std::hash<typename range_value_t<R>::first_type>,
|
|
||||||
typename E = std::equal_to<typename range_value_t<R>::first_type>,
|
|
||||||
typename A = std::allocator<std::pair<
|
|
||||||
std::tuple_element_t<0, range_value_t<R>>,
|
|
||||||
std::tuple_element_t<1, range_value_t<R>>
|
|
||||||
>>
|
|
||||||
>
|
|
||||||
inline std::unordered_map<
|
|
||||||
std::tuple_element_t<0, range_value_t<R>>,
|
|
||||||
std::tuple_element_t<1, range_value_t<R>>, H, E, A
|
|
||||||
> make_unordered_map(
|
|
||||||
R &&range, std::size_t bcount = 1, H const &hash = H{},
|
|
||||||
E const &kequal = E{}, A const &alloc = A{}
|
|
||||||
) {
|
|
||||||
static_assert(
|
|
||||||
detail::is_2tuple_like<range_value_t<R>>,
|
|
||||||
"the range element must be a pair/2-tuple"
|
|
||||||
);
|
|
||||||
return make_unordered_map<
|
|
||||||
std::tuple_element_t<0, range_value_t<R>>,
|
|
||||||
std::tuple_element_t<1, range_value_t<R>>, H, E, A
|
|
||||||
>(std::forward<R>(range), bcount, hash, kequal, alloc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
} /* namespace ostd */
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** @} */
|
|
|
@ -1,84 +0,0 @@
|
||||||
/** @defgroup Containers
|
|
||||||
*
|
|
||||||
* @brief New containers and extensions to standard containers.
|
|
||||||
*
|
|
||||||
* libostd adds various new utilities for standard containers that allow
|
|
||||||
* besides other things construction of those containers from ranges.
|
|
||||||
*
|
|
||||||
* Integration of ranges for iteration is however not necessary because
|
|
||||||
* there is already a fully generic integration for anything that provides
|
|
||||||
* an iterator interface.
|
|
||||||
*
|
|
||||||
* New containers will also be implemented where necessary.
|
|
||||||
*
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** @file vector.hh
|
|
||||||
*
|
|
||||||
* @brief Extensions for std::vector.
|
|
||||||
*
|
|
||||||
* This file provides extensions for the standard std::vector container.
|
|
||||||
*
|
|
||||||
* @copyright See COPYING.md in the project tree for further information.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef OSTD_VECTOR_HH
|
|
||||||
#define OSTD_VECTOR_HH
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <memory>
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
#include "ostd/range.hh"
|
|
||||||
|
|
||||||
namespace ostd {
|
|
||||||
|
|
||||||
/** @addtogroup Containers
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** @brief Creates a vector using a range.
|
|
||||||
*
|
|
||||||
* Given a range `range` and optionally an allocator, this constructs
|
|
||||||
* an std::vector, adding each item of the given range to it.
|
|
||||||
*
|
|
||||||
* You have to manually specify the type of the vector's values. There
|
|
||||||
* is also another version with the type decided from the range.
|
|
||||||
*
|
|
||||||
* @tparam T The value type of the vector.
|
|
||||||
*/
|
|
||||||
template<typename T, typename A = std::allocator<T>, typename R>
|
|
||||||
inline std::vector<T, A> make_vector(R range, A const &alloc = A{}) {
|
|
||||||
std::vector<T, A> ret{alloc};
|
|
||||||
using C = range_category_t<R>;
|
|
||||||
if constexpr(std::is_convertible_v<C, contiguous_range_tag>) {
|
|
||||||
ret.reserve(range.size());
|
|
||||||
ret.insert(ret.end(), range.data(), range.data() + range.size());
|
|
||||||
} else {
|
|
||||||
for (; !range.empty(); range.pop_front()) {
|
|
||||||
ret.push_back(range.front());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @brief Creates a vector using a range.
|
|
||||||
*
|
|
||||||
* Calls into make_vector() using the range value type as the vector
|
|
||||||
* value type.
|
|
||||||
*/
|
|
||||||
template<typename R, typename A = std::allocator<range_value_t<R>>>
|
|
||||||
inline std::vector<range_value_t<R>, A> make_vector(
|
|
||||||
R &&range, A const &alloc = A{}
|
|
||||||
) {
|
|
||||||
return make_vector<range_value_t<R>, A>(std::forward<R>(range), alloc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
} /* namespace ostd */
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** @} */
|
|
|
@ -1,7 +1,8 @@
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
#include <ostd/platform.hh>
|
#include <ostd/platform.hh>
|
||||||
#include <ostd/io.hh>
|
#include <ostd/io.hh>
|
||||||
#include <ostd/string.hh>
|
#include <ostd/string.hh>
|
||||||
#include <ostd/unordered_map.hh>
|
|
||||||
#include <ostd/filesystem.hh>
|
#include <ostd/filesystem.hh>
|
||||||
#include <ostd/environ.hh>
|
#include <ostd/environ.hh>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue