Skip to content
Snippets Groups Projects
Commit 32225717 authored by namark's avatar namark
Browse files

index_range for what it's worth

parent d3fa6597
No related branches found
No related tags found
No related merge requests found
......@@ -9,6 +9,7 @@
#include <cinttypes>
#include "range.hpp"
#include "algorithm/utils.hpp"
namespace simple::support
{
......@@ -129,11 +130,64 @@ namespace simple::support
}
template <typename It>
[[deprecated("use simple::support::string_view from simple/support/algorithm/range_wrappers.hpp")]]
std::string_view make_string_view(It begin, It end)
{
return {begin, static_cast<std::string_view::size_type>(end - begin)};
}
// NOTE: maybe put in algorithm range wrappers instead?
template <typename Container,
typename = std::enable_if_t<is_range_v<Container>>>
class index_range
{
public:
using container_type = Container;
using size_type = typename container_type::size_type;
explicit index_range
(
Container & container,
range<size_type> index = range<size_type>::limit()
) :
container(&container),
index(index)
{}
explicit index_range
(
Container & container,
range<typename Container::const_iterator> iterator_range
) :
container(&container),
index(iterator_range - container.begin())
{}
auto begin() const
{ return iter_at(index.lower()); }
auto end() const
{ return iter_at(index.upper()); }
private:
Container* container;
range<size_type> index;
auto iter_at(size_type index) const
{
using std::begin;
using std::end;
using std::clamp;
auto begin_ = begin(*container);
auto end_ = end(*container);
// TODO: use container.size() if available
return begin_ + clamp(index, size_type{},
static_cast<size_type>(end_ - begin_)); // good cast, since container can not have negative size
}
};
} // namespace simple::support
#endif /* end of include guard */
......@@ -101,11 +101,47 @@ void SimplifiedToNumber()
to_<unsigned char>(std::to_string(std::numeric_limits<unsigned char>::max()) + '0'));
}
void RangeReference()
{
using std::begin;
using std::end;
const std::string prefix = "Permaprefix";
std::string stuff{prefix};
range temporef{begin(stuff), end(stuff)};
assert( std::equal(begin(temporef), end(temporef),
begin(prefix), end(prefix)) );
index_range permaref(stuff, {begin(stuff), end(stuff)});
assert( std::equal(begin(permaref), end(permaref),
begin(prefix), end(prefix)) );
stuff += " now this a really really long long paragraph of text, that should by all means cause reallocation and stuff, so the iterators in temporef range will be invalidated, while permaref that uses indices will remain valid and usable... though it doesn't really matter if it actually relocates since there is no way to check any of this, you'll just have to believe me and trust me and never ever let me go...";
// can't do this anymore
// assert( std::equal(begin(temporef), end(temporef),
// begin(prefix), end(prefix)) );
// asan might not catch this, because of small string optimization, and since you are allowed to reinterpret anything as char* it might not even be UB dependent on the implementation, but then the assertion will fail at least
// otherwise the assertion might not fail, if the old/freed memory happens to remain untouched by either the system or the allocator
// so asan and assert together can kind of catch this I guess
// TODO: __gnu_debug::string (but not std::string under _GLIBCXX_DEBUG, it's an obscure exception) does catch this reliably, so that's a thing to consider for unit testing purposes in general
// all ok here
assert( std::equal(begin(permaref), end(permaref),
begin(prefix), end(prefix)) );
}
int main()
{
StringToNumber();
StringToNumericRange();
NumericRangeToString();
SimplifiedToNumber();
RangeReference();
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment