Skip to content

Instantly share code, notes, and snippets.

@gatchamix
Last active August 27, 2017 16:59
Show Gist options
  • Save gatchamix/62966808f4d5f2120389b0491fc973c8 to your computer and use it in GitHub Desktop.
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)
#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