Last active
August 27, 2017 16:59
-
-
Save gatchamix/62966808f4d5f2120389b0491fc973c8 to your computer and use it in GitHub Desktop.
template type and non-type list and manipulation functions (type_t/auto_t)
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 <type_traits> | |
#include <limits> | |
#include <utility> | |
// | |
template <class... Ts> | |
struct type_t | |
{ static auto constexpr size = sizeof...(Ts); }; | |
template <class... Ts> | |
auto constexpr type_v = type_t<Ts...>{}; | |
template <class... L, class... R> | |
auto constexpr operator+(type_t<L...>, type_t<R...>) | |
{ return type_t<L..., R...>{}; } | |
template <class... L, class... R> | |
auto constexpr operator==(type_t<L...>, type_t<R...>) | |
{ return std::is_same_v<type_t<L...>, type_t<R...>>; } | |
// broken in GCC | |
//template <class T, class... Ts> | |
//auto constexpr remove(type_t<T> = {}, type_t<Ts...> = {}) | |
//{ | |
// return ([] | |
// { | |
// if constexpr (std::is_same_v<T, Ts>) | |
// { return type_v<>; } | |
// else | |
// { return type_v<Ts>; } | |
// }() + ...); | |
//} | |
namespace detail | |
{ | |
template <class L, class R> | |
auto constexpr remove_impl__() | |
{ | |
if constexpr (std::is_same_v<L, R>) | |
{ return type_v<>; } | |
else | |
{ return type_v<R>; } | |
} | |
} | |
template <class T, class... Ts> | |
auto constexpr remove(type_t<T> = {}, type_t<Ts...> = {}) | |
{ return ((detail::remove_impl__<T, Ts>()) + ...); } | |
// C++2a | |
//template <class T, class... Ts> | |
//auto constexpr find(type_t<T> = {}, type_t<Ts...> = {}) | |
//{ | |
// return | |
// []<auto... Is>(std::index_sequence<Is...>) | |
// { | |
// auto idx = sizeof...(Ts) + 1; | |
// ((std::is_same_v<T, Ts> ? idx = Is : 0) || ...); | |
// return idx; | |
// } | |
// (std::make_index_sequence<sizeof...(Ts)>{}); | |
//} | |
namespace detail | |
{ | |
template <class T, class... Ts, auto... Is> | |
auto constexpr find_impl__(type_t<T>, type_t<Ts...>, std::index_sequence<Is...>) | |
{ | |
auto idx = sizeof...(Ts) + 1; | |
((std::is_same_v<T, Ts> ? idx = Is : 0)|| ...); | |
return idx; | |
} | |
} | |
template <class T, class... Ts> | |
auto constexpr find(type_t<T> t = {}, type_t<Ts...> ts = {}) | |
{ return find_impl__(t, ts, std::make_index_sequence<sizeof...(Ts)>{}); } | |
template <class T, class... Ts> | |
auto constexpr contains(type_t<T> = {}, type_t<Ts...> = {}) | |
{ return (std::is_same_v<T, Ts> || ...); } | |
// | |
template <auto... Vs> | |
struct auto_t | |
{ | |
static auto constexpr size = sizeof...(Vs); | |
using types = type_t<decltype(Vs)...>; | |
}; | |
template <auto... Vs> | |
auto constexpr auto_v = auto_t<Vs...>{}; | |
template <char... Vs> | |
auto constexpr operator ""_c() | |
{ return auto_v<Vs...>; } | |
template <auto... L, auto... R> | |
auto constexpr operator+(auto_t<L...>, auto_t<R...>) | |
{ return auto_t<L..., R...>{}; } | |
template <auto... L, auto... R> | |
auto constexpr operator==(auto_t<L...>, auto_t<R...>) | |
{ return std::is_same_v<auto_t<L...>, auto_t<R...>>; } | |
template <auto... Vs> | |
auto constexpr min(auto_t<Vs...>) | |
{ | |
using type = std::common_type_t<decltype(Vs)...>; | |
auto val = std::numeric_limits<type>::max(); | |
(((val > Vs) ? val = Vs : 0), ...); | |
return val; | |
} | |
template <auto... Vs> | |
auto constexpr max(auto_t<Vs...>) | |
{ | |
using type = std::common_type_t<decltype(Vs)...>; | |
auto val = std::numeric_limits<type>::min(); | |
(((val < Vs) ? val = Vs : 0), ...); | |
return val; | |
} | |
// broken in GCC | |
//template <auto V, auto... Vs> | |
//auto constexpr remove(auto_t<V> = {}, auto_t<Vs...> = {}) | |
//{ | |
// return ([] | |
// { | |
// if constexpr (V == Vs) | |
// { return auto_v<>; } | |
// else | |
// { return auto_v<Vs>; } | |
// }() + ...); | |
//} | |
namespace detail | |
{ | |
template <auto L, auto R> | |
auto constexpr remove_impl__() | |
{ | |
if constexpr (L == R) | |
{ return auto_v<>; } | |
else | |
{ return auto_v<R>; } | |
} | |
} | |
template <auto V, auto... Vs> | |
auto constexpr remove(auto_t<V> = {}, auto_t<Vs...> = {}) | |
{ return ((detail::remove_impl__<V, Vs>()) + ...); } | |
template <auto V, auto... Vs> | |
auto constexpr contains(auto_t<V> = {}, auto_t<Vs...> = {}) | |
{ return ((V == Vs) || ...); } | |
// C++2a | |
//template <auto V, auto... Vs> | |
//auto constexpr find(auto_t<V> = {}, auto_t<Vs...> = {}) | |
//{ | |
// return | |
// []<auto... Is>(std::index_sequence<Is...>) | |
// { | |
// auto idx = sizeof...(Vs) + 1; | |
// ((V == Vs ? idx = Is : 0) || ...); | |
// return idx; | |
// } | |
// (std::make_index_sequence<sizeof...(Vs)>{}); | |
//} | |
namespace detail | |
{ | |
template <auto V, auto... Vs, auto... Is> | |
auto constexpr find_impl__(auto_t<V>, auto_t<Vs...>, std::index_sequence<Is...>) | |
{ | |
auto val = sizeof...(Vs) + 1; | |
((V == Vs ? val = Is : 0)|| ...); | |
return val; | |
} | |
} | |
template <auto V, auto... Vs> | |
auto constexpr find(auto_t<V> v = {}, auto_t<Vs...> vs = {}) | |
{ return find_impl__(v, vs, std::make_index_sequence<sizeof...(Vs)>{}); } | |
// | |
template <class...> | |
struct common_type; | |
template <class... Ts> | |
struct common_type<type_t<Ts...>> | |
{ using type = std::common_type_t<Ts...>; }; | |
template <auto... Vs> | |
struct common_type<auto_t<Vs...>> | |
{ using type = std::common_type_t<decltype(Vs)...>; }; | |
int main() | |
{ | |
auto constexpr a = 12131_c; | |
auto constexpr b = 41516_c; | |
auto constexpr c = a + auto_v<' '> + b; | |
auto constexpr d = remove(1_c, c); | |
static_assert(d); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment