argparser/src/distinct-types.h
2023-05-17 10:17:56 +02:00

52 lines
1.9 KiB
C++

#ifndef ARGPARSER_DISTINCT_TYPES_H
#define ARGPARSER_DISTINCT_TYPES_H
#include <type_traits>
#include <variant>
namespace argparser::internal::distinct_types_impl {
template<typename TList, typename... Ts>
struct UniqueTypes;
template<template<typename...> typename X, typename... Ts>
struct UniqueTypes<X<Ts...>> {
using type = X<Ts...>;
};
template<template<typename...> typename X, typename... Ts, typename T, typename... Us>
struct UniqueTypes<X<Ts...>, T, Us...> {
using type = typename UniqueTypes<
typename std::conditional<
std::disjunction<std::is_same<T, Ts>...>::value,
X<Ts...>,
X<Ts..., T>>::type,
Us...>::type;
};
template<template<typename...> typename X, typename... Ts>
struct Distinct {
using type = typename UniqueTypes<X<>, Ts...>::type;
};
}// namespace argparser::internal::distinct_types_impl
namespace argparser::internal {
template<typename... Ts>
using distinct_types_variant = typename internal::distinct_types_impl::Distinct<std::variant, Ts...>::type;
template<typename... Ts>
using distinct_types_tuple = typename internal::distinct_types_impl::Distinct<std::tuple, Ts...>::type;
template<typename T, typename... Ts>
using if_single_type = std::enable_if_t<std::tuple_size<distinct_types_tuple<Ts...>>::value == 1, T>;
template<typename T, typename... Ts>
using if_not_single_type = std::enable_if_t<(std::tuple_size<distinct_types_tuple<Ts...>>::value > 1), T>;
template<typename T, typename F, typename... Ts>
using single_type_conditional = std::conditional<(std::tuple_size<distinct_types_tuple<Ts...>>::value == 1), T, F>;
template<typename... Ts>
using single_type = if_single_type<typename std::tuple_element<0, std::tuple<Ts...>>::type, Ts...>;
}// namespace argparser::internal
#endif// ARGPARSER_DISTINCT_TYPES_H