From 0842a24cd3191a5b50e28445d9c9f31a986204e5 Mon Sep 17 00:00:00 2001 From: q66 Date: Wed, 1 Feb 2017 20:56:19 +0100 Subject: [PATCH] complete template param support for all ranged make_ funcs and ranged_traits --- ostd/string.hh | 47 ++++++++++++++++++++++++------------ ostd/unordered_map.hh | 55 ++++++++++++++++++++++++++++++++----------- ostd/vector.hh | 28 ++++++++++++---------- 3 files changed, 89 insertions(+), 41 deletions(-) diff --git a/ostd/string.hh b/ostd/string.hh index cb18d3c..b993770 100644 --- a/ostd/string.hh +++ b/ostd/string.hh @@ -12,6 +12,7 @@ #include #include +#include #include "ostd/utility.hh" #include "ostd/range.hh" @@ -246,33 +247,49 @@ inline bool starts_with(ConstCharRange a, ConstCharRange b) { return a.slice(0, b.size()) == b; } -template -struct ranged_traits> { - static CharRangeBase iter(std::basic_string &v) { +template +struct ranged_traits> { + static CharRangeBase iter(std::basic_string &v) { return CharRangeBase{v.data(), v.size()}; } }; -template -struct ranged_traits const> { - static CharRangeBase iter(std::basic_string const &v) { +template +struct ranged_traits const> { + static CharRangeBase iter(std::basic_string const &v) { return CharRangeBase{v.data(), v.size()}; } }; -template -inline std::basic_string make_string(R range) { - /* TODO: specialize for contiguous ranges and matching value types */ - std::basic_string ret; - for (; !range.empty(); range.pop_front()) { - ret.push_back(range.front()); +template< + typename T, typename TR = std::char_traits, + typename A = std::allocator, typename R +> +inline std::basic_string make_string(R range, A const &alloc = A{}) { + std::basic_string ret{alloc}; + using C = RangeCategory; + if constexpr(std::is_convertible_v) { + /* 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; } -template -inline std::basic_string>> make_string(R range) { - return make_string>>(std::move(range)); +template< + typename R, typename TR = std::char_traits>>, + typename A = std::allocator>> +> +inline std::basic_string>, TR, A> make_string( + R range, A const &alloc = A{} +) { + return make_string>, TR, A>(std::move(range), alloc); } /* string literals */ diff --git a/ostd/unordered_map.hh b/ostd/unordered_map.hh index f537f7b..320bf69 100644 --- a/ostd/unordered_map.hh +++ b/ostd/unordered_map.hh @@ -7,45 +7,72 @@ #define OSTD_UNORDERED_MAP_HH #include +#include #include "ostd/range.hh" namespace ostd { -template -struct ranged_traits> { - using Range = IteratorRange::iterator>; - static Range iter(std::unordered_map &v) { +template +struct ranged_traits> { + using Range = IteratorRange< + typename std::unordered_map::iterator + >; + static Range iter(std::unordered_map &v) { return Range{v.begin(), v.end()}; } }; -template -struct ranged_traits const> { - using Range = IteratorRange::const_iterator>; - static Range iter(std::unordered_map const &v) { +template +struct ranged_traits const> { + using Range = IteratorRange< + typename std::unordered_map::const_iterator + >; + static Range iter(std::unordered_map const &v) { return Range{v.cbegin(), v.cend()}; } }; -template -inline std::unordered_map make_unordered_map(R range) { - std::unordered_map ret; +template< + typename K, typename T, typename H = std::hash, + typename E = std::equal_to, + typename A = std::allocator>, typename R +> +inline std::unordered_map make_unordered_map( + R range, size_t bcount = 1, H const &hash = H{}, + E const &kequal = E{}, A const &alloc = A{} +) { + std::unordered_map ret{bcount, hash, kequal, alloc}; + using C = RangeCategory; + if constexpr(std::is_convertible_v) { + /* at least try to preallocate here... */ + ret.reserve(range.size()); + } for (; !range.empty(); range.pop_front()) { ret.emplace(range.front()); } return ret; } -template +template< + typename R, + typename H = std::hash::first_type>, + typename E = std::equal_to::first_type>, + typename A = std::allocator::first_type, typename RangeValue::second_type + >> +> inline std::unordered_map< typename RangeValue::first_type, typename RangeValue::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< typename RangeValue::first_type, typename RangeValue::second_type - >(std::forward(range)); + >(std::forward(range), bcount, hash, kequal, alloc); } } /* namespace ostd */ diff --git a/ostd/vector.hh b/ostd/vector.hh index 5c747ac..da1a71c 100644 --- a/ostd/vector.hh +++ b/ostd/vector.hh @@ -7,33 +7,35 @@ #define OSTD_VECTOR_HH #include +#include #include #include "ostd/range.hh" namespace ostd { -template -struct ranged_traits> { - static PointerRange iter(std::vector &v) { +template +struct ranged_traits> { + static PointerRange iter(std::vector &v) { return PointerRange{v.data(), v.size()}; } }; -template -struct ranged_traits const> { - static PointerRange iter(std::vector const &v) { +template +struct ranged_traits const> { + static PointerRange iter(std::vector const &v) { return PointerRange{v.data(), v.size()}; } }; -template -inline std::vector make_vector(R range) { - std::vector ret; +template, typename R> +inline std::vector make_vector(R range, A const &alloc = A{}) { + std::vector ret{alloc}; using C = RangeCategory; if constexpr(std::is_convertible_v) { /* 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 */ @@ -44,9 +46,11 @@ inline std::vector make_vector(R range) { return ret; } -template -inline std::vector> make_vector(R &&range) { - return make_vector>(std::forward(range)); +template>> +inline std::vector, A> make_vector( + R &&range, A const &alloc = A{} +) { + return make_vector, A>(std::forward(range), alloc); } } /* namespace ostd */