Created
February 27, 2015 05:03
-
-
Save pfultz2/c302423e40cd02a33e76 to your computer and use it in GitHub Desktop.
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
#include <iostream> | |
#include <vector> | |
#include <list> | |
#include <tick/builder.h> | |
#include <tick/requires.h> | |
#include <fit/lambda.h> | |
#include <fit/function.h> | |
#include <fit/conditional.h> | |
#include <fit/reveal.h> | |
// clang++-3.4 -std=c++1y -I../../../github/Fit -I../../../github/Tick -DUSE_CONDITIONAL_OVERLOADING overloading-1.cpp | |
TICK_TRAIT(is_incrementable) | |
{ | |
template<class T> | |
auto require(T&& x) -> valid< | |
decltype(x++), | |
decltype(++x) | |
>; | |
}; | |
TICK_TRAIT(is_decrementable, is_incrementable<_>) | |
{ | |
template<class T> | |
auto require(T&& x) -> valid< | |
decltype(x--), | |
decltype(--x) | |
>; | |
}; | |
TICK_TRAIT(is_advanceable) | |
{ | |
template<class T, class Number> | |
auto require(T&& x, Number n) -> valid< | |
decltype(x += n) | |
>; | |
}; | |
#ifdef USE_SFINAE | |
template<class Iterator, TICK_REQUIRES(is_advanceable<Iterator, int>())> | |
void advance(Iterator& it, int n) | |
{ | |
it += n; | |
} | |
template<class Iterator, TICK_REQUIRES(is_decrementable<Iterator>() and | |
not is_advanceable<Iterator, int>())> | |
void advance(Iterator& it, int n) | |
{ | |
if (n > 0) while (n--) ++it; | |
else | |
{ | |
n *= -1; | |
while (n--) --it; | |
} | |
} | |
template<class Iterator, TICK_REQUIRES(is_incrementable<Iterator>() and | |
not is_advanceable<Iterator, int>() and | |
not is_decrementable<Iterator>())> | |
void advance(Iterator& it, int n) | |
{ | |
while (n--) ++it; | |
} | |
#endif | |
#ifdef USE_TAG_DISPATCHING | |
struct incrementable_tag {}; | |
struct decrementable_tag : incrementable_tag {}; | |
struct advanceable_tag : decrementable_tag, incrementable_tag {}; | |
template<class T, class=void> | |
struct get_advance_tag; | |
template<class T> | |
struct get_advance_tag<T, TICK_CLASS_REQUIRES(is_advanceable<T, int>())> | |
{ using type = advanceable_tag; }; | |
template<class T> | |
struct get_advance_tag<T, TICK_CLASS_REQUIRES(is_decrementable<T>() and | |
not is_advanceable<T, int>())> | |
{ using type = decrementable_tag; }; | |
template<class T> | |
struct get_advance_tag<T, TICK_CLASS_REQUIRES(is_incrementable<T>() and | |
not is_advanceable<T, int>() and | |
not is_decrementable<T>())> | |
{ using type = incrementable_tag; }; | |
template<class Iterator> | |
void advance_impl(Iterator& it, int n, const advanceable_tag&) | |
{ | |
it += n; | |
} | |
template<class Iterator> | |
void advance_impl(Iterator& it, int n, const decrementable_tag&) | |
{ | |
if (n > 0) while (n--) ++it; | |
else | |
{ | |
n *= -1; | |
while (n--) --it; | |
} | |
} | |
template<class Iterator> | |
void advance_impl(Iterator& it, int n, const incrementable_tag&) | |
{ | |
while (n--) ++it; | |
} | |
template<class Iterator> | |
void advance(Iterator& it, int n) | |
{ | |
advance_impl(it, n, typename get_advance_tag<Iterator>::type()); | |
} | |
#endif | |
#ifdef USE_RANK | |
template<int N> | |
struct rank : rank<N-1> {}; | |
template<> | |
struct rank<0> {}; | |
template<class Iterator, TICK_REQUIRES(is_advanceable<Iterator, int>())> | |
void advance_impl(Iterator& it, int n, const rank<3>&) | |
{ | |
it += n; | |
} | |
template<class Iterator, TICK_REQUIRES(is_decrementable<Iterator>())> | |
void advance_impl(Iterator& it, int n, const rank<2>&) | |
{ | |
if (n > 0) while (n--) ++it; | |
else | |
{ | |
n *= -1; | |
while (n--) --it; | |
} | |
} | |
template<class Iterator, TICK_REQUIRES(is_incrementable<Iterator>())> | |
void advance_impl(Iterator& it, int n, const rank<1>&) | |
{ | |
while (n--) ++it; | |
} | |
template<class Iterator> | |
void advance(Iterator& it, int n) | |
{ | |
advance_impl(it, n, rank<3>()); | |
} | |
#endif | |
#ifdef USE_CONDITIONAL_OVERLOADING | |
// const constexpr auto advance = fit::conditional( | |
// FIT_STATIC_LAMBDA(auto& it, int n, TICK_PARAM_REQUIRES(tick::trait<is_advanceable>(it, n))) | |
// { | |
// it += n; | |
// }, | |
// FIT_STATIC_LAMBDA(auto& it, int n, TICK_PARAM_REQUIRES(tick::trait<is_decrementable>(it))) | |
// { | |
// if (n > 0) while (n--) ++it; | |
// else | |
// { | |
// n *= -1; | |
// while (n--) --it; | |
// } | |
// }, | |
// FIT_STATIC_LAMBDA(auto& it, int n, TICK_PARAM_REQUIRES(tick::trait<is_incrementable>(it))) | |
// { | |
// while (n--) ++it; | |
// } | |
// ); | |
FIT_STATIC_FUNCTION(advance) = fit::conditional( | |
[](auto& it, int n, TICK_PARAM_REQUIRES(tick::trait<is_advanceable>(it, n))) | |
{ | |
it += n; | |
}, | |
[](auto& it, int n, TICK_PARAM_REQUIRES(tick::trait<is_decrementable>(it))) | |
{ | |
if (n > 0) while (n--) ++it; | |
else | |
{ | |
n *= -1; | |
while (n--) --it; | |
} | |
}, | |
[](auto& it, int n, TICK_PARAM_REQUIRES(tick::trait<is_incrementable>(it))) | |
{ | |
while (n--) ++it; | |
} | |
); | |
#endif | |
void check_list() | |
{ | |
std::list<int> l = { 1, 2, 3, 4, 5, 6 }; | |
auto iterator = l.begin(); | |
advance(iterator, 4); | |
std::cout << *iterator << std::endl; | |
} | |
void check_reverse_list() | |
{ | |
std::list<int> l = { 1, 2, 3, 4, 5, 6 }; | |
auto iterator = l.end(); | |
advance(iterator, -4); | |
std::cout << *iterator << std::endl; | |
} | |
void check_vector() | |
{ | |
std::vector<int> v = { 1, 2, 3, 4, 5, 6 }; | |
auto iterator = v.begin(); | |
advance(iterator, 4); | |
std::cout << *iterator << std::endl; | |
} | |
struct foo {}; | |
int main() | |
{ | |
// advance(foo(), 1); | |
// fit::reveal(advance)(foo(), 1); | |
check_list(); | |
check_reverse_list(); | |
check_vector(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment