complete template param support for all ranged make_ funcs and ranged_traits

This commit is contained in:
q66 2017-02-01 20:56:19 +01:00
parent 84f01c1286
commit 0842a24cd3
3 changed files with 89 additions and 41 deletions

View file

@ -12,6 +12,7 @@
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <type_traits>
#include "ostd/utility.hh" #include "ostd/utility.hh"
#include "ostd/range.hh" #include "ostd/range.hh"
@ -246,33 +247,49 @@ inline bool starts_with(ConstCharRange a, ConstCharRange b) {
return a.slice(0, b.size()) == b; return a.slice(0, b.size()) == b;
} }
template<typename T> template<typename T, typename TR, typename A>
struct ranged_traits<std::basic_string<T>> { struct ranged_traits<std::basic_string<T, TR, A>> {
static CharRangeBase<T> iter(std::basic_string<T> &v) { static CharRangeBase<T> iter(std::basic_string<T, TR, A> &v) {
return CharRangeBase<T>{v.data(), v.size()}; return CharRangeBase<T>{v.data(), v.size()};
} }
}; };
template<typename T> template<typename T, typename TR, typename A>
struct ranged_traits<std::basic_string<T> const> { struct ranged_traits<std::basic_string<T, TR, A> const> {
static CharRangeBase<T const> iter(std::basic_string<T> const &v) { static CharRangeBase<T const> iter(std::basic_string<T, TR, A> const &v) {
return CharRangeBase<T const>{v.data(), v.size()}; return CharRangeBase<T const>{v.data(), v.size()};
} }
}; };
template<typename T, typename R> template<
inline std::basic_string<T> make_string(R range) { typename T, typename TR = std::char_traits<T>,
/* TODO: specialize for contiguous ranges and matching value types */ typename A = std::allocator<T>, typename R
std::basic_string<T> ret; >
for (; !range.empty(); range.pop_front()) { inline std::basic_string<T, TR, A> make_string(R range, A const &alloc = A{}) {
ret.push_back(range.front()); std::basic_string<T, TR, A> ret{alloc};
using C = RangeCategory<R>;
if constexpr(std::is_convertible_v<C, FiniteRandomAccessRangeTag>) {
/* finite random access or contiguous */
auto h = range.half();
ret.reserve(range.size());
ret.insert(ret.end(), h, h + range.size());
} else {
/* infinite random access and below */
for (; !range.empty(); range.pop_front()) {
ret.push_back(range.front());
}
} }
return ret; return ret;
} }
template<typename R> template<
inline std::basic_string<RemoveCv<RangeValue<R>>> make_string(R range) { typename R, typename TR = std::char_traits<RemoveCv<RangeValue<R>>>,
return make_string<RemoveCv<RangeValue<R>>>(std::move(range)); typename A = std::allocator<RemoveCv<RangeValue<R>>>
>
inline std::basic_string<RemoveCv<RangeValue<R>>, TR, A> make_string(
R range, A const &alloc = A{}
) {
return make_string<RemoveCv<RangeValue<R>>, TR, A>(std::move(range), alloc);
} }
/* string literals */ /* string literals */

View file

@ -7,45 +7,72 @@
#define OSTD_UNORDERED_MAP_HH #define OSTD_UNORDERED_MAP_HH
#include <unordered_map> #include <unordered_map>
#include <type_traits>
#include "ostd/range.hh" #include "ostd/range.hh"
namespace ostd { namespace ostd {
template<typename K, typename T> template<typename K, typename T, typename H, typename E, typename A>
struct ranged_traits<std::unordered_map<K, T>> { struct ranged_traits<std::unordered_map<K, T, H, E, A>> {
using Range = IteratorRange<typename std::unordered_map<K, T>::iterator>; using Range = IteratorRange<
static Range iter(std::unordered_map<K, T> &v) { typename std::unordered_map<K, T, H, E, A>::iterator
>;
static Range iter(std::unordered_map<K, T, H, E, A> &v) {
return Range{v.begin(), v.end()}; return Range{v.begin(), v.end()};
} }
}; };
template<typename K, typename T> template<typename K, typename T, typename H, typename E, typename A>
struct ranged_traits<std::unordered_map<K, T> const> { struct ranged_traits<std::unordered_map<K, T, H, E, A> const> {
using Range = IteratorRange<typename std::unordered_map<K, T>::const_iterator>; using Range = IteratorRange<
static Range iter(std::unordered_map<K, T> const &v) { typename std::unordered_map<K, T, H, E, A>::const_iterator
>;
static Range iter(std::unordered_map<K, T, H, E, A> const &v) {
return Range{v.cbegin(), v.cend()}; return Range{v.cbegin(), v.cend()};
} }
}; };
template<typename K, typename T, typename R> template<
inline std::unordered_map<K, T> make_unordered_map(R range) { typename K, typename T, typename H = std::hash<K>,
std::unordered_map<K, T> ret; typename E = std::equal_to<K>,
typename A = std::allocator<std::pair<K const, T>>, typename R
>
inline std::unordered_map<K, T> make_unordered_map(
R range, size_t bcount = 1, H const &hash = H{},
E const &kequal = E{}, A const &alloc = A{}
) {
std::unordered_map<K, T> ret{bcount, hash, kequal, alloc};
using C = RangeCategory<R>;
if constexpr(std::is_convertible_v<C, FiniteRandomAccessRangeTag>) {
/* at least try to preallocate here... */
ret.reserve(range.size());
}
for (; !range.empty(); range.pop_front()) { for (; !range.empty(); range.pop_front()) {
ret.emplace(range.front()); ret.emplace(range.front());
} }
return ret; return ret;
} }
template<typename R> template<
typename R,
typename H = std::hash<typename RangeValue<R>::first_type>,
typename E = std::equal_to<typename RangeValue<R>::first_type>,
typename A = std::allocator<std::pair<
typename RangeValue<R>::first_type, typename RangeValue<R>::second_type
>>
>
inline std::unordered_map< inline std::unordered_map<
typename RangeValue<R>::first_type, typename RangeValue<R>::first_type,
typename RangeValue<R>::second_type typename RangeValue<R>::second_type
> make_unordered_map(R &&range) { > make_unordered_map(
R &&range, size_t bcount = 1, H const &hash = H{},
E const &kequal = E{}, A const &alloc = A{}
) {
return make_unordered_map< return make_unordered_map<
typename RangeValue<R>::first_type, typename RangeValue<R>::first_type,
typename RangeValue<R>::second_type typename RangeValue<R>::second_type
>(std::forward<R>(range)); >(std::forward<R>(range), bcount, hash, kequal, alloc);
} }
} /* namespace ostd */ } /* namespace ostd */

View file

@ -7,33 +7,35 @@
#define OSTD_VECTOR_HH #define OSTD_VECTOR_HH
#include <vector> #include <vector>
#include <memory>
#include <type_traits> #include <type_traits>
#include "ostd/range.hh" #include "ostd/range.hh"
namespace ostd { namespace ostd {
template<typename T> template<typename T, typename A>
struct ranged_traits<std::vector<T>> { struct ranged_traits<std::vector<T, A>> {
static PointerRange<T> iter(std::vector<T> &v) { static PointerRange<T> iter(std::vector<T, A> &v) {
return PointerRange<T>{v.data(), v.size()}; return PointerRange<T>{v.data(), v.size()};
} }
}; };
template<typename T> template<typename T, typename A>
struct ranged_traits<std::vector<T> const> { struct ranged_traits<std::vector<T, A> const> {
static PointerRange<T const> iter(std::vector<T> const &v) { static PointerRange<T const> iter(std::vector<T, A> const &v) {
return PointerRange<T const>{v.data(), v.size()}; return PointerRange<T const>{v.data(), v.size()};
} }
}; };
template<typename T, typename R> template<typename T, typename A = std::allocator<T>, typename R>
inline std::vector<T> make_vector(R range) { inline std::vector<T, A> make_vector(R range, A const &alloc = A{}) {
std::vector<T> ret; std::vector<T, A> ret{alloc};
using C = RangeCategory<R>; using C = RangeCategory<R>;
if constexpr(std::is_convertible_v<C, FiniteRandomAccessRangeTag>) { if constexpr(std::is_convertible_v<C, FiniteRandomAccessRangeTag>) {
/* finite random access or contiguous */ /* finite random access or contiguous */
auto h = range.half(); auto h = range.half();
ret.reserve(range.size());
ret.insert(ret.end(), h, h + range.size()); ret.insert(ret.end(), h, h + range.size());
} else { } else {
/* infinite random access and below */ /* infinite random access and below */
@ -44,9 +46,11 @@ inline std::vector<T> make_vector(R range) {
return ret; return ret;
} }
template<typename R> template<typename R, typename A = std::allocator<RangeValue<R>>>
inline std::vector<RangeValue<R>> make_vector(R &&range) { inline std::vector<RangeValue<R>, A> make_vector(
return make_vector<RangeValue<R>>(std::forward<R>(range)); R &&range, A const &alloc = A{}
) {
return make_vector<RangeValue<R>, A>(std::forward<R>(range), alloc);
} }
} /* namespace ostd */ } /* namespace ostd */