get rid of namespace internal

master
Daniel Kolesa 2015-04-24 18:16:35 +01:00
parent cca0a62d34
commit f106c5ae24
4 changed files with 326 additions and 311 deletions

View File

@ -12,7 +12,7 @@ go beyond C++11 level when it comes to core language features.
Compiler | Version Compiler | Version
-------- | ------- -------- | -------
gcc/g++ | 4.8+ gcc/g++ | 4.8+
clang | 3.4+ clang | 3.3+
MSVC++ | 2015+ MSVC++ | 2015+
Other C++11 compliant compilers might work as well. OctaSTD does not utilize Other C++11 compliant compilers might work as well. OctaSTD does not utilize

View File

@ -14,6 +14,8 @@
#include "octa/initializer_list.h" #include "octa/initializer_list.h"
namespace octa { namespace octa {
/* partitioning */
template<typename R, typename U> template<typename R, typename U>
R partition(R range, U pred) { R partition(R range, U pred) {
R ret = range; R ret = range;
@ -34,6 +36,8 @@ namespace octa {
return true; return true;
} }
/* insertion sort */
template<typename R, typename C> template<typename R, typename C>
void insertion_sort(R range, C compare) { void insertion_sort(R range, C compare) {
size_t rlen = range.length(); size_t rlen = range.length();
@ -52,76 +56,76 @@ namespace octa {
insertion_sort(range, Less<typename RangeTraits<R>::value>()); insertion_sort(range, Less<typename RangeTraits<R>::value>());
} }
namespace internal { /* sort (introsort) */
template<typename T, typename U>
struct UnaryCompare {
const T &val;
U comp;
bool operator()(const T &v) const { return comp(v, val); }
};
template<typename R, typename C> template<typename T, typename U>
void hs_sift_down(R range, size_t s, size_t e, C compare) { struct __OctaUnaryCompare {
size_t r = s; const T &val;
while ((r * 2 + 1) <= e) { U comp;
size_t ch = r * 2 + 1; bool operator()(const T &v) const { return comp(v, val); }
size_t sw = r; };
if (compare(range[sw], range[ch]))
sw = ch;
if (((ch + 1) <= e) && compare(range[sw], range[ch + 1]))
sw = ch + 1;
if (sw != r) {
swap(range[r], range[sw]);
r = sw;
} else return;
}
}
template<typename R, typename C> template<typename R, typename C>
void heapsort(R range, C compare) { void __octa_hs_sift_down(R range, size_t s, size_t e, C compare) {
size_t len = range.length(); size_t r = s;
size_t st = (len - 2) / 2; while ((r * 2 + 1) <= e) {
for (;;) { size_t ch = r * 2 + 1;
hs_sift_down(range, st, len - 1, compare); size_t sw = r;
if (st-- == 0) break; if (compare(range[sw], range[ch]))
} sw = ch;
size_t e = len - 1; if (((ch + 1) <= e) && compare(range[sw], range[ch + 1]))
while (e > 0) { sw = ch + 1;
swap(range[e], range[0]); if (sw != r) {
--e; swap(range[r], range[sw]);
hs_sift_down(range, 0, e, compare); r = sw;
} } else return;
}
template<typename R, typename C>
void introloop(R range, C compare, size_t depth) {
if (range.length() <= 10) {
insertion_sort(range, compare);
return;
}
if (depth == 0) {
heapsort(range, compare);
return;
}
typename RangeTraits<R>::reference p = range[range.length() / 2];
swap(p, range.last());
R r = partition(range, UnaryCompare<decltype(p), C>{ p, compare });
R l = range.slice(0, range.length() - r.length());
swap(r.first(), r.last());
introloop(l, compare, depth - 1);
introloop(r, compare, depth - 1);
}
template<typename R, typename C>
void introsort(R range, C compare) {
introloop(range, compare, size_t(2
* (log(range.length()) / log(2))));
} }
} }
template<typename R, typename C>
void __octa_heapsort(R range, C compare) {
size_t len = range.length();
size_t st = (len - 2) / 2;
for (;;) {
__octa_hs_sift_down(range, st, len - 1, compare);
if (st-- == 0) break;
}
size_t e = len - 1;
while (e > 0) {
swap(range[e], range[0]);
--e;
__octa_hs_sift_down(range, 0, e, compare);
}
}
template<typename R, typename C>
void __octa_introloop(R range, C compare, size_t depth) {
if (range.length() <= 10) {
insertion_sort(range, compare);
return;
}
if (depth == 0) {
__octa_heapsort(range, compare);
return;
}
typename RangeTraits<R>::reference p = range[range.length() / 2];
swap(p, range.last());
R r = partition(range, __OctaUnaryCompare<decltype(p), C>{ p, compare });
R l = range.slice(0, range.length() - r.length());
swap(r.first(), r.last());
__octa_introloop(l, compare, depth - 1);
__octa_introloop(r, compare, depth - 1);
}
template<typename R, typename C>
void __octa_introsort(R range, C compare) {
__octa_introloop(range, compare, size_t(2
* (log(range.length()) / log(2))));
}
template<typename R, typename C> template<typename R, typename C>
void sort(R range, C compare) { void sort(R range, C compare) {
internal::introsort(range, compare); __octa_introsort(range, compare);
} }
template<typename R> template<typename R>
@ -129,6 +133,8 @@ namespace octa {
sort(range, Less<typename RangeTraits<R>::value>()); sort(range, Less<typename RangeTraits<R>::value>());
} }
/* min/max(_element) */
template<typename T> template<typename T>
inline const T &min(const T &a, const T &b) { inline const T &min(const T &a, const T &b) {
return (a < b) ? a : b; return (a < b) ? a : b;
@ -200,6 +206,8 @@ namespace octa {
return max_element(il.range(), compare).first(); return max_element(il.range(), compare).first();
} }
/* algos that don't change the range */
template<typename R, typename F> template<typename R, typename F>
F for_each(R range, F func) { F for_each(R range, F func) {
for (; !range.empty(); range.pop_first()) for (; !range.empty(); range.pop_first())
@ -289,6 +297,8 @@ namespace octa {
return range2.empty(); return range2.empty();
} }
/* algos that modify ranges or work with output ranges */
template<typename R1, typename R2> template<typename R1, typename R2>
R2 copy(R1 irange, R2 orange) { R2 copy(R1 irange, R2 orange) {
for (; !irange.empty(); irange.pop_first()) for (; !irange.empty(); irange.pop_first())

View File

@ -12,7 +12,9 @@
#include "octa/traits.h" #include "octa/traits.h"
namespace octa { namespace octa {
#define OCTA_DEFINE_BINARY_OP(name, op, rettype) \ /* basic function objects */
#define __OCTA_DEFINE_BINARY_OP(name, op, rettype) \
template<typename T> struct name { \ template<typename T> struct name { \
bool operator()(const T &x, const T &y) const { return x op y; } \ bool operator()(const T &x, const T &y) const { return x op y; } \
struct type { \ struct type { \
@ -22,24 +24,24 @@ namespace octa {
}; \ }; \
}; };
OCTA_DEFINE_BINARY_OP(Less, <, bool) __OCTA_DEFINE_BINARY_OP(Less, <, bool)
OCTA_DEFINE_BINARY_OP(LessEqual, <=, bool) __OCTA_DEFINE_BINARY_OP(LessEqual, <=, bool)
OCTA_DEFINE_BINARY_OP(Greater, >, bool) __OCTA_DEFINE_BINARY_OP(Greater, >, bool)
OCTA_DEFINE_BINARY_OP(GreaterEqual, >=, bool) __OCTA_DEFINE_BINARY_OP(GreaterEqual, >=, bool)
OCTA_DEFINE_BINARY_OP(Equal, ==, bool) __OCTA_DEFINE_BINARY_OP(Equal, ==, bool)
OCTA_DEFINE_BINARY_OP(NotEqual, !=, bool) __OCTA_DEFINE_BINARY_OP(NotEqual, !=, bool)
OCTA_DEFINE_BINARY_OP(LogicalAnd, &&, bool) __OCTA_DEFINE_BINARY_OP(LogicalAnd, &&, bool)
OCTA_DEFINE_BINARY_OP(LogicalOr, ||, bool) __OCTA_DEFINE_BINARY_OP(LogicalOr, ||, bool)
OCTA_DEFINE_BINARY_OP(Modulus, %, T) __OCTA_DEFINE_BINARY_OP(Modulus, %, T)
OCTA_DEFINE_BINARY_OP(Multiplies, *, T) __OCTA_DEFINE_BINARY_OP(Multiplies, *, T)
OCTA_DEFINE_BINARY_OP(Divides, /, T) __OCTA_DEFINE_BINARY_OP(Divides, /, T)
OCTA_DEFINE_BINARY_OP(Plus, +, T) __OCTA_DEFINE_BINARY_OP(Plus, +, T)
OCTA_DEFINE_BINARY_OP(Minus, -, T) __OCTA_DEFINE_BINARY_OP(Minus, -, T)
OCTA_DEFINE_BINARY_OP(BitAnd, &, T) __OCTA_DEFINE_BINARY_OP(BitAnd, &, T)
OCTA_DEFINE_BINARY_OP(BitOr, |, T) __OCTA_DEFINE_BINARY_OP(BitOr, |, T)
OCTA_DEFINE_BINARY_OP(BitXor, ^, T) __OCTA_DEFINE_BINARY_OP(BitXor, ^, T)
#undef OCTA_DEFINE_BINARY_OP #undef __OCTA_DEFINE_BINARY_OP
template<typename T> struct LogicalNot { template<typename T> struct LogicalNot {
bool operator()(const T &x) const { return !x; } bool operator()(const T &x) const { return !x; }
@ -93,6 +95,8 @@ namespace octa {
return BinaryNegate<T>(fn); return BinaryNegate<T>(fn);
} }
/* reference wrapper */
template<typename T> template<typename T>
struct ReferenceWrapper { struct ReferenceWrapper {
typedef T type; typedef T type;
@ -126,64 +130,64 @@ namespace octa {
} }
template<typename T> void cref(const T &&) = delete; template<typename T> void cref(const T &&) = delete;
namespace internal { /* mem_fn */
template<typename, typename> struct MemTypes;
template<typename T, typename R, typename ...A>
struct MemTypes<T, R(A...)> {
typedef R result;
typedef T argument;
};
template<typename T, typename R, typename A>
struct MemTypes<T, R(A)> {
typedef R result;
typedef T first;
typedef A second;
};
template<typename T, typename R, typename ...A>
struct MemTypes<T, R(A...) const> {
typedef R result;
typedef const T argument;
};
template<typename T, typename R, typename A>
struct MemTypes<T, R(A) const> {
typedef R result;
typedef const T first;
typedef A second;
};
template<typename R, typename T> template<typename, typename> struct __OctaMemTypes;
class MemFn { template<typename T, typename R, typename ...A>
R T::*p_ptr; struct __OctaMemTypes<T, R(A...)> {
public: typedef R result;
struct type: MemTypes<T, R> {}; typedef T argument;
};
MemFn(R T::*ptr): p_ptr(ptr) {} template<typename T, typename R, typename A>
template<typename... A> struct __OctaMemTypes<T, R(A)> {
auto operator()(T &obj, A &&...args) -> typedef R result;
decltype(((obj).*(p_ptr))(forward<A>(args)...)) { typedef T first;
return ((obj).*(p_ptr))(forward<A>(args)...); typedef A second;
} };
template<typename... A> template<typename T, typename R, typename ...A>
auto operator()(const T &obj, A &&...args) -> struct __OctaMemTypes<T, R(A...) const> {
decltype(((obj).*(p_ptr))(forward<A>(args)...)) const { typedef R result;
return ((obj).*(p_ptr))(forward<A>(args)...); typedef const T argument;
} };
template<typename... A> template<typename T, typename R, typename A>
auto operator()(T *obj, A &&...args) -> struct __OctaMemTypes<T, R(A) const> {
decltype(((obj)->*(p_ptr))(forward<A>(args)...)) { typedef R result;
return ((obj)->*(p_ptr))(forward<A>(args)...); typedef const T first;
} typedef A second;
template<typename... A> };
auto operator()(const T *obj, A &&...args) ->
decltype(((obj)->*(p_ptr))(forward<A>(args)...)) const {
return ((obj)->*(p_ptr))(forward<A>(args)...);
}
};
}
template<typename R, typename T> template<typename R, typename T>
internal::MemFn<R, T> mem_fn(R T:: *ptr) { class __OctaMemFn {
return internal::MemFn<R, T>(ptr); R T::*p_ptr;
public:
struct type: __OctaMemTypes<T, R> {};
__OctaMemFn(R T::*ptr): p_ptr(ptr) {}
template<typename... A>
auto operator()(T &obj, A &&...args) ->
decltype(((obj).*(p_ptr))(forward<A>(args)...)) {
return ((obj).*(p_ptr))(forward<A>(args)...);
}
template<typename... A>
auto operator()(const T &obj, A &&...args) ->
decltype(((obj).*(p_ptr))(forward<A>(args)...)) const {
return ((obj).*(p_ptr))(forward<A>(args)...);
}
template<typename... A>
auto operator()(T *obj, A &&...args) ->
decltype(((obj)->*(p_ptr))(forward<A>(args)...)) {
return ((obj)->*(p_ptr))(forward<A>(args)...);
}
template<typename... A>
auto operator()(const T *obj, A &&...args) ->
decltype(((obj)->*(p_ptr))(forward<A>(args)...)) const {
return ((obj)->*(p_ptr))(forward<A>(args)...);
}
};
template<typename R, typename T>
__OctaMemFn<R, T> mem_fn(R T:: *ptr) {
return __OctaMemFn<R, T>(ptr);
} }
/* function impl /* function impl
@ -192,158 +196,161 @@ namespace octa {
template<typename> struct Function; template<typename> struct Function;
namespace internal { struct __OctaFunctorData {
struct FunctorData { void *p1, *p2;
void *p1, *p2; };
};
template<typename T> template<typename T>
struct FunctorInPlace { struct __OctaFunctorInPlace {
static constexpr bool value = sizeof(T) <= sizeof(FunctorData) static constexpr bool value = sizeof(T) <= sizeof(__OctaFunctorData)
&& (alignof(FunctorData) % alignof(T)) == 0 && (alignof(__OctaFunctorData) % alignof(T)) == 0
&& octa::IsNothrowMoveConstructible<T>::value; && octa::IsNothrowMoveConstructible<T>::value;
}; };
template<typename T, typename E = void> template<typename T, typename E = void>
struct FunctorDataManager { struct __OctaFunctorDataManager {
template<typename R, typename ...A> template<typename R, typename ...A>
static R call(const FunctorData &s, A ...args) { static R call(const __OctaFunctorData &s, A ...args) {
return ((T &)s)(forward<A>(args)...); return ((T &)s)(forward<A>(args)...);
}
static void store_f(FunctorData &s, T v) {
new (&get_ref(s)) T(forward<T>(v));
}
static void move_f(FunctorData &lhs, FunctorData &&rhs) {
new (&get_ref(lhs)) T(move(get_ref(rhs)));
}
static void destroy_f(FunctorData &s) {
get_ref(s).~T();
}
static T &get_ref(const FunctorData &s) {
return (T &)s;
}
};
template<typename T>
struct FunctorDataManager<T, typename EnableIf<!FunctorInPlace<T>
::value>::type> {
template<typename R, typename ...A>
static R call(const FunctorData &s, A ...args) {
return (*(T *&)s)(forward<A>(args)...);
}
static void store_f(FunctorData &s, T v) {
new (&get_ptr_ref(s)) T *(new T(forward<T>(v)));
}
static void move_f(FunctorData &lhs, FunctorData &&rhs) {
new (&get_ptr_ref(lhs)) T *(get_ptr_ref(rhs));
get_ptr_ref(rhs) = nullptr;
}
static void destroy_f(FunctorData &s) {
T *&ptr = get_ptr_ref(s);
if (!ptr) return;
delete ptr;
ptr = nullptr;
}
static T &get_ref(const FunctorData &s) {
return *get_ptr_ref(s);
}
static T *&get_ptr_ref(FunctorData &s) {
return (T *&)s;
}
static T *&get_ptr_ref(const FunctorData &s) {
return (T *&)s;
}
};
struct FunctionManager;
struct ManagerStorage {
FunctorData data;
const FunctionManager *manager;
};
template<typename T>
static const FunctionManager &get_default_manager();
struct FunctionManager {
template<typename T>
inline static const FunctionManager create_default_manager() {
return FunctionManager {
&t_call_move_and_destroy<T>,
&t_call_copy<T>,
&t_call_destroy<T>
};
}
void (* const call_move_and_destroy)(ManagerStorage &lhs, ManagerStorage &&rhs);
void (* const call_copy)(ManagerStorage &lhs, const ManagerStorage &rhs);
void (* const call_destroy)(ManagerStorage &s);
template<typename T>
static void t_call_move_and_destroy(ManagerStorage &lhs, ManagerStorage &&rhs) {
typedef FunctorDataManager<T> spec;
spec::move_f(lhs.data, move(rhs.data));
spec::destroy_f(rhs.data);
lhs.manager = &get_default_manager<T>();
}
template<typename T>
static void t_call_copy(ManagerStorage &lhs, const ManagerStorage &rhs) {
typedef FunctorDataManager<T> spec;
lhs.manager = &get_default_manager<T>();
spec::store_f(lhs.data, spec::get_ref(rhs.data));
}
template<typename T>
static void t_call_destroy(ManagerStorage &s) {
typedef FunctorDataManager<T> spec;
spec::destroy_f(s.data);
}
};
template<typename T>
inline static const FunctionManager &get_default_manager() {
static const FunctionManager def_manager = FunctionManager::create_default_manager<T>();
return def_manager;
} }
template<typename R, typename...> static void store_f(__OctaFunctorData &s, T v) {
struct FunctionBase { new (&get_ref(s)) T(forward<T>(v));
struct type { }
typedef R result;
};
};
template<typename R, typename T> static void move_f(__OctaFunctorData &lhs, __OctaFunctorData &&rhs) {
struct FunctionBase<R, T> { new (&get_ref(lhs)) T(move(get_ref(rhs)));
struct type { }
typedef R result;
typedef T argument;
};
};
template<typename R, typename T, typename U> static void destroy_f(__OctaFunctorData &s) {
struct FunctionBase<R, T, U> { get_ref(s).~T();
struct type { }
typedef R result;
typedef T first; static T &get_ref(const __OctaFunctorData &s) {
typedef U second; return (T &)s;
}
};
template<typename T>
struct __OctaFunctorDataManager<T, typename EnableIf<!__OctaFunctorInPlace<T>
::value>::type> {
template<typename R, typename ...A>
static R call(const __OctaFunctorData &s, A ...args) {
return (*(T *&)s)(forward<A>(args)...);
}
static void store_f(__OctaFunctorData &s, T v) {
new (&get_ptr_ref(s)) T *(new T(forward<T>(v)));
}
static void move_f(__OctaFunctorData &lhs, __OctaFunctorData &&rhs) {
new (&get_ptr_ref(lhs)) T *(get_ptr_ref(rhs));
get_ptr_ref(rhs) = nullptr;
}
static void destroy_f(__OctaFunctorData &s) {
T *&ptr = get_ptr_ref(s);
if (!ptr) return;
delete ptr;
ptr = nullptr;
}
static T &get_ref(const __OctaFunctorData &s) {
return *get_ptr_ref(s);
}
static T *&get_ptr_ref(__OctaFunctorData &s) {
return (T *&)s;
}
static T *&get_ptr_ref(const __OctaFunctorData &s) {
return (T *&)s;
}
};
struct __OctaFunctionManager;
struct __OctaFMStorage {
__OctaFunctorData data;
const __OctaFunctionManager *manager;
};
template<typename T>
static const __OctaFunctionManager &__octa_get_default_fm();
struct __OctaFunctionManager {
template<typename T>
inline static const __OctaFunctionManager create_default_manager() {
return __OctaFunctionManager {
&t_call_move_and_destroy<T>,
&t_call_copy<T>,
&t_call_destroy<T>
}; };
}; }
void (* const call_move_and_destroy)(__OctaFMStorage &lhs,
__OctaFMStorage &&rhs);
void (* const call_copy)(__OctaFMStorage &lhs,
const __OctaFMStorage &rhs);
void (* const call_destroy)(__OctaFMStorage &s);
template<typename T>
static void t_call_move_and_destroy(__OctaFMStorage &lhs,
__OctaFMStorage &&rhs) {
typedef __OctaFunctorDataManager<T> spec;
spec::move_f(lhs.data, move(rhs.data));
spec::destroy_f(rhs.data);
lhs.manager = &__octa_get_default_fm<T>();
}
template<typename T>
static void t_call_copy(__OctaFMStorage &lhs,
const __OctaFMStorage &rhs) {
typedef __OctaFunctorDataManager<T> spec;
lhs.manager = &__octa_get_default_fm<T>();
spec::store_f(lhs.data, spec::get_ref(rhs.data));
}
template<typename T>
static void t_call_destroy(__OctaFMStorage &s) {
typedef __OctaFunctorDataManager<T> spec;
spec::destroy_f(s.data);
}
};
template<typename T>
inline static const __OctaFunctionManager &__octa_get_default_fm() {
static const __OctaFunctionManager def_manager
= __OctaFunctionManager::create_default_manager<T>();
return def_manager;
} }
template<typename R, typename...>
struct __OctaFunction {
struct type {
typedef R result;
};
};
template<typename R, typename T>
struct __OctaFunction<R, T> {
struct type {
typedef R result;
typedef T argument;
};
};
template<typename R, typename T, typename U>
struct __OctaFunction<R, T, U> {
struct type {
typedef R result;
typedef T first;
typedef U second;
};
};
template<typename R, typename ...A> template<typename R, typename ...A>
struct Function<R(A...)>: internal::FunctionBase<R, A...> { struct Function<R(A...)>: __OctaFunction<R, A...> {
Function( ) { initialize_empty(); } Function( ) { initialize_empty(); }
Function(nullptr_t) { initialize_empty(); } Function(nullptr_t) { initialize_empty(); }
@ -391,7 +398,7 @@ namespace octa {
} }
void swap(Function &f) { void swap(Function &f) {
internal::ManagerStorage tmp; __OctaFMStorage tmp;
f.p_stor.manager->call_move_and_destroy(tmp, move(f.p_stor)); f.p_stor.manager->call_move_and_destroy(tmp, move(f.p_stor));
p_stor.manager->call_move_and_destroy(f.p_stor, move(p_stor)); p_stor.manager->call_move_and_destroy(f.p_stor, move(p_stor));
tmp.manager->call_move_and_destroy(p_stor, move(tmp)); tmp.manager->call_move_and_destroy(p_stor, move(tmp));
@ -401,21 +408,21 @@ namespace octa {
operator bool() const { return p_call != nullptr; } operator bool() const { return p_call != nullptr; }
private: private:
internal::ManagerStorage p_stor; __OctaFMStorage p_stor;
R (*p_call)(const internal::FunctorData &, A...); R (*p_call)(const __OctaFunctorData &, A...);
template<typename T> template<typename T>
void initialize(T f) { void initialize(T f) {
p_call = &internal::FunctorDataManager<T>::template call<R, A...>; p_call = &__OctaFunctorDataManager<T>::template call<R, A...>;
p_stor.manager = &internal::get_default_manager<T>(); p_stor.manager = &__octa_get_default_fm<T>();
internal::FunctorDataManager<T>::store_f(p_stor.data, forward<T>(f)); __OctaFunctorDataManager<T>::store_f(p_stor.data, forward<T>(f));
} }
void initialize_empty() { void initialize_empty() {
typedef R(*emptyf)(A...); typedef R(*emptyf)(A...);
p_call = nullptr; p_call = nullptr;
p_stor.manager = &internal::get_default_manager<emptyf>(); p_stor.manager = &__octa_get_default_fm<emptyf>();
internal::FunctorDataManager<emptyf>::store_f(p_stor.data, nullptr); __OctaFunctorDataManager<emptyf>::store_f(p_stor.data, nullptr);
} }
template<typename T> template<typename T>

View File

@ -25,26 +25,24 @@ namespace octa {
typedef typename T::type::reference reference; typedef typename T::type::reference reference;
}; };
namespace internal { template<typename T>
template<typename T> struct __OctaRangeIterator {
struct RangeIterator { __OctaRangeIterator(): p_range() {}
RangeIterator(): p_range() {} explicit __OctaRangeIterator(const T &range): p_range(range) {}
explicit RangeIterator(const T &range): p_range(range) {} __OctaRangeIterator &operator++() {
RangeIterator &operator++() { p_range.pop_first();
p_range.pop_first(); return *this;
return *this; }
} typename RangeTraits<T>::reference operator*() {
typename RangeTraits<T>::reference operator*() { return p_range.first();
return p_range.first(); }
} typename RangeTraits<T>::reference operator*() const {
typename RangeTraits<T>::reference operator*() const { return p_range.first();
return p_range.first(); }
} bool operator!=(__OctaRangeIterator) const { return !p_range.empty(); }
bool operator!=(RangeIterator) const { return !p_range.empty(); } private:
private: T p_range;
T p_range; };
};
}
template<typename B, typename C, typename V, typename R = V &> template<typename B, typename C, typename V, typename R = V &>
struct InputRangeBase { struct InputRangeBase {
@ -54,11 +52,11 @@ namespace octa {
typedef R reference; typedef R reference;
}; };
internal::RangeIterator<B> begin() { __OctaRangeIterator<B> begin() {
return internal::RangeIterator<B>((const B &)*this); return __OctaRangeIterator<B>((const B &)*this);
} }
internal::RangeIterator<B> end() { __OctaRangeIterator<B> end() {
return internal::RangeIterator<B>(); return __OctaRangeIterator<B>();
} }
}; };