Skip to content

Instantly share code, notes, and snippets.

@Redchards
Created December 20, 2015 12:38
Show Gist options
  • Select an option

  • Save Redchards/95aed7b1efdd5e11e7ce to your computer and use it in GitHub Desktop.

Select an option

Save Redchards/95aed7b1efdd5e11e7ce to your computer and use it in GitHub Desktop.
Extremly simple range classes, inspired by Eric Niebler's work.
// #include <Meta.hxx>
// Normally I use my little metaprogramming class, but it should be easy to adapt the code to use something better
// (or maybe standard C++ when it got more metaprogramming features)
// If you don't care, you can grab my little library here
// https://gist.github.com/Redchards/c7a454adb151e79f4e9d
template<class T>
static constexpr bool is_empty_and_trivial = std::is_empty<T>::value && std::is_trivial<T>::value;
template<class T>
using empty_and_trivial_enabler = std::enable_if_t<std::is_empty<T>::value && std::is_trivial<T>::value>;
template<class T>
struct basic_pair_attribute
{
using value_type = T;
basic_pair_attribute() = default;
template<class Arg>
constexpr explicit basic_pair_attribute(Arg&&)
{
static_assert(std::is_constructible<value_type, Arg>::value,
"Type can't be constructed from the passed argument types");
}
};
template<class T, class = void>
struct first_pair_attribute : public basic_pair_attribute<T>
{
T first;
first_pair_attribute() = default;
template<class Arg>
constexpr explicit first_pair_attribute(Arg&& arg)
: base(std::forward<Arg>(arg)), first(std::forward<Arg>(arg))
{}
private:
using base = basic_pair_attribute<T>;
};
template<class T>
struct first_pair_attribute<T,
meta::void_t<empty_and_trivial_enabler<T>>
> : public basic_pair_attribute<T>
{
static T first;
};
template<class T>
T first_pair_attribute<T, meta::void_t<empty_and_trivial_enabler<T>>>::first{};
template<class T, class = void>
struct last_pair_attribute : public basic_pair_attribute<T>
{
T last;
last_pair_attribute() = default;
template<class Arg>
constexpr explicit last_pair_attribute(Arg&& arg)
: base(std::forward<Arg>(arg)), last(std::forward<Arg>(arg))
{}
private:
using base = basic_pair_attribute<T>;
};
template<class T>
struct last_pair_attribute<T,
meta::void_t<empty_and_trivial_enabler<T>>
> : public basic_pair_attribute<T>
{
static T last;
};
template<class T>
T last_pair_attribute<T, meta::void_t<empty_and_trivial_enabler<T>>>::last{};
template<class First, class Last>
struct reduced_pair
: public first_pair_attribute<First>,
public last_pair_attribute<Last>
{
using first_type = First;
using last_type = Last;
using first_base = first_pair_attribute<first_type>;
using last_base = last_pair_attribute<last_type>;
template<class Arg1, class Arg2>
constexpr explicit reduced_pair(Arg1&& t, Arg2&& u)
: first_base(std::forward<Arg1>(t)), last_base(std::forward<Arg2>(u))
{}
template<class T1, class Arg2>
constexpr explicit reduced_pair(std::initializer_list<T1> list, Arg2&& u)
: first_base(list), last_base(std::forward<Arg2>(u))
{}
template<class Arg1, class T2>
constexpr explicit reduced_pair(Arg1&& t, std::initializer_list<T2> list)
: first_base(std::forward<Arg1>(t)), last_base(list)
{}
template<class T1, class T2>
constexpr explicit reduced_pair(std::initializer_list<T1> list1, std::initializer_list<T2> list2)
: first_base(list1), last_base(list2)
{}
constexpr operator std::pair<First, Last>()
{
return {this->first, this->last};
}
};
template<class Iterator>
struct range : private reduced_pair<Iterator, Iterator>
{
using iterator = Iterator;
using base = reduced_pair<Iterator, Iterator>;
using reduced_pair<Iterator, Iterator>::first;
using reduced_pair<Iterator, Iterator>::last;
range() = default;
constexpr range(iterator first, iterator last)
: base(std::move(first), std::move(last))
{}
template<class OtherIterator,
typename = std::enable_if_t<std::is_convertible<OtherIterator, Iterator>::value>>
constexpr range(range<OtherIterator> rg)
: range(rg.first, rg.last)
{}
template<class OtherIterator1, class OtherIterator2,
typename = std::enable_if_t<std::is_convertible<OtherIterator1, Iterator>::value && std::is_convertible<OtherIterator2, Iterator>::value>>
constexpr range(std::pair<OtherIterator1, OtherIterator2> rg)
: range(rg.first, rg.last)
{}
iterator begin()
{
return first;
}
iterator end()
{
return last;
}
};
using string_range = range<std::string::iterator>;
using const_string_range = range<std::string::iterator>;
class multi_string_range
{
public:
using iterator = std::string::iterator;
public:
multi_string_range(iterator first, iterator last)
: range_vector{{std::move(first), std::move(last)}}
{};
template<class Iterator,
typename = std::enable_if_t<std::is_convertible<Iterator, iterator>::value>>
multi_string_range(range<Iterator> rg)
: range_vector{{rg.begin(), rg.end()}}
{};
std::string str() const
{
std::string tmp;
for(auto range : range_vector)
{
tmp += {range.first, range.last};
}
return tmp;
}
private:
std::vector<string_range> range_vector;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment