Skip to content

Instantly share code, notes, and snippets.

@pfultz2
Created February 27, 2015 05:03
Show Gist options
  • Save pfultz2/c302423e40cd02a33e76 to your computer and use it in GitHub Desktop.
Save pfultz2/c302423e40cd02a33e76 to your computer and use it in GitHub Desktop.
#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