Created
August 19, 2016 19:26
-
-
Save FreeSlave/0a6eebcb289f8847c181a0f9e7e8bd1b to your computer and use it in GitHub Desktop.
Use STL iterators to iterate over zero terminated string without calling of strlen
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright (c) 2016 Roman Chistokhodov | |
// Distributed under the Boost Software License, Version 1.0. | |
// http://www.boost.org/LICENSE_1_0.txt | |
/* | |
* Q: Why? | |
* A: The idea is to use STL iterators to iterate over zero terminated string without calling of strlen to evaluate the end iterator. | |
* | |
* Q: Why not random access? | |
* A: Currently the 'end' iterator is implemented as NULL and it's not obvious how it should work with '-' (minus) operator, | |
* which is required by random access iterator concept. | |
* | |
* Q: Why not bidirectional? | |
* A: Same issue, but with '--' operator. | |
*/ | |
#include <iterator> | |
#include <cstdlib> | |
#include <algorithm> | |
#include <cassert> | |
template<typename T> | |
struct CStringIterator : public std::iterator<std::forward_iterator_tag, T> | |
{ | |
CStringIterator(T* str) : _ptr(str) {} | |
CStringIterator() : _ptr(0) {} | |
T& operator*() { | |
return *_ptr; | |
} | |
T* operator->() { | |
return _ptr; | |
} | |
CStringIterator& operator++() { | |
++_ptr; | |
return *this; | |
} | |
CStringIterator operator++(int) { | |
CStringIterator toReturn = *this; | |
++_ptr; | |
return toReturn; | |
} | |
CStringIterator operator+=(std::ptrdiff_t add) { | |
_ptr += add; | |
} | |
CStringIterator operator+(std::ptrdiff_t add) const { | |
return CStringIterator(_ptr + add); | |
} | |
bool operator==(const CStringIterator& other) const { | |
return equal(other); | |
} | |
bool operator!=(const CStringIterator& other) const { | |
return !equal(other); | |
} | |
T* ptr() const { | |
return _ptr; | |
} | |
private: | |
inline bool equal(const CStringIterator& other) const { | |
return (_ptr == other._ptr) || (this->atEnd() && other.atEnd()); | |
} | |
inline bool atEnd() const { | |
return !_ptr || !*_ptr; | |
} | |
T* _ptr; | |
}; | |
template<typename T> | |
CStringIterator<T> operator+(std::ptrdiff_t value, const CStringIterator<T>& it) { | |
return value + it.ptr(); | |
} | |
int main() | |
{ | |
typedef CStringIterator<const char> CIterator; | |
const char* str = "Hello"; | |
CIterator begin(str); | |
CIterator end; | |
assert(*begin == 'H'); | |
assert(begin + 5 == end); | |
assert(5 + begin == end); | |
assert(begin != end); | |
assert(end != begin); | |
CIterator it = begin; | |
CIterator it2 = ++it; | |
assert(*it == 'e'); | |
assert(it == it2); | |
it2 = it++; | |
assert(*it == 'l'); | |
assert(*it2 == 'e'); | |
assert(std::equal(begin, end, "Hello")); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment