Skip to content

Instantly share code, notes, and snippets.

@lennyerik
Created November 10, 2023 14:09
Show Gist options
  • Save lennyerik/2b3aaf83e5a0176a5eb9235d089c4f97 to your computer and use it in GitHub Desktop.
Save lennyerik/2b3aaf83e5a0176a5eb9235d089c4f97 to your computer and use it in GitHub Desktop.
A generic string splitting iterator in C++20
#include <iostream>
#include <iterator>
#include <cstring>
template<typename T>
concept HasLengthMethod = requires(T t) {
{ t.length() } -> std::same_as<std::size_t>;
};
template<typename T>
concept CanBePassedToStrlen = requires(T t) {
{ strlen(t) } -> std::same_as<std::size_t>;
};
template<typename S>
requires (HasLengthMethod<S> || CanBePassedToStrlen<S> || std::same_as<S, char>)
std::size_t generic_strlen(S s) {
if constexpr (HasLengthMethod<S>) {
return s.length();
} else if constexpr (CanBePassedToStrlen<S>) {
return strlen(s);
} else {
return 1;
}
}
template<typename D>
requires requires(D d) {
std::string_view("").find(d);
generic_strlen(d);
}
class Split {
public:
using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = std::string_view;
using pointer = std::string_view;
using reference = std::string_view;
Split(std::string_view input, D delimiter) : input(input), delimiter(delimiter) {}
reference operator*() const {
return this->input.substr(0, this->input.find(this->delimiter));
}
pointer operator->() const {
return this->input.substr(0, this->input.find(this->delimiter));
}
Split& operator++() {
const std::size_t pos = this->input.find(this->delimiter);
const std::size_t delimiter_len = generic_strlen(this->delimiter);
this->input = this->input.substr(
pos == std::string_view::npos ? this->input.length() : pos + delimiter_len
);
return *this;
}
friend bool operator==(const Split& a, const Split& b) {
return a.input.length() == b.input.length();
}
friend bool operator!=(const Split& a, const Split& b) {
return a.input.length() != b.input.length();
}
Split begin() {
return *this;
}
Split end() {
return Split("", this->delimiter);
}
private:
std::string_view input;
D delimiter;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment