Skip to content

Instantly share code, notes, and snippets.

@Voultapher
Created November 22, 2016 15:24
Show Gist options
  • Save Voultapher/2e10175222268824ab86586773da5e09 to your computer and use it in GitHub Desktop.
Save Voultapher/2e10175222268824ab86586773da5e09 to your computer and use it in GitHub Desktop.
#ifndef TUPLEFOLD_CONCEPTS_H_INCLUDED
#define TUPLEFOLD_CONCEPTS_H_INCLUDED
#include <type_traits>
#include <string>
namespace util
{
template<bool CONDITION> struct true_if : std::conditional_t<CONDITION,
std::true_type,
std::false_type
> {};
template<bool...> struct bool_pack;
template<bool... b> using all_true = std::is_same<bool_pack<true, b...>, bool_pack<b..., true>>;
template<bool... b> using all_false = std::is_same<bool_pack<false, b...>, bool_pack<b..., false>>;
template<typename T, template <typename> class Expression> class compiles
{
private:
struct exists;
struct lacks;
template<typename C, typename F = Expression<C>> static exists overload(int ph);
template<typename C> static lacks overload(...);
public:
static const bool value = std::is_same<decltype(overload<T>(0)), exists>::value;
};
template<
typename T,
template <typename> class Func,
template <typename> class Ret
>
class expression_returns
{
private:
struct lacks_func;
struct lacks_ret;
template<typename C, typename F = Func<C>> static F overload_func(int ph);
template<typename C> static lacks_func overload_func(...);
template<typename C, typename R = Ret<C>> static R overload_ret(int ph);
template<typename C> static lacks_ret overload_ret(...);
public:
static const bool value = std::is_same<
decltype(overload_func<T>(0)),
decltype(overload_ret<T>(0))
>::value;
};
// --- def ---
template<typename T> using def_begin = decltype(std::declval<T>().begin());
template<typename T> using def_end = decltype(std::declval<T>().end());
template<typename T> using def_iterator_deref = decltype(
std::declval<typename T::iterator>().operator*()
);
template<typename T> using def_to_string = decltype(std::to_string(std::declval<T>()));
// --- type ---
template<typename T> using type_iterator = typename T::iterator;
template<typename T> using type_iterator_const = const typename T::iterator;
template<typename T> using type_val = typename T::value_type&;
template<typename T> using type_val_const = const typename T::value_type&;
// --- has ---
template<typename T> using has_range_begin = true_if<
expression_returns<T, def_begin, type_iterator>::value
|| expression_returns<T, def_begin, type_iterator_const>::value
>;
template<typename T> using has_range_end = true_if<
expression_returns<T, def_end, type_iterator>::value
|| expression_returns<T, def_end, type_iterator_const>::value
>;
template<typename T> using has_range_iterator = true_if<
expression_returns<T, def_iterator_deref, type_val>::value
|| expression_returns<T, def_iterator_deref, type_val_const>::value
>;
// --- is ---
template<typename T> using is_range = true_if<
has_range_begin<T>::value
&& has_range_end<T>::value
//&& has_range_iterator<T>::value
>;
template<typename T> using is_stream_convert = true_if<
compiles<T, def_to_string>::value
|| std::is_convertible<T, std::string>::value
>;
// --- requires ---
template<
typename Result,
typename T,
template<typename> class... Cons
>
using requires = std::enable_if_t<
all_true<Cons<T>::value...>::value,
Result
>;
template<
typename Result,
typename T,
template<typename> class... Cons
>
using fallback = std::enable_if_t<
all_false<Cons<T>::value...>::value,
Result
>;
}
#endif // TUPLEFOLD_CONCEPTS_H_INCLUDED
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment