Created
November 22, 2016 15:24
-
-
Save Voultapher/2e10175222268824ab86586773da5e09 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
#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