- . - 0 , 1 + .
, , , - , . , .
template <class... > struct typelist { };
template <class >
struct uniq;
template <class TL>
using uniq_t = typename uniq<TL>::type;
template <>
struct uniq<typelist<>> {
using type = typelist<>;
};
template <class T, class... Ts>
struct uniq<typelist<T, Ts...>>
: concat<typelist<T>, uniq_t<filter_out_t<T, typelist<Ts...>>>>
{ };
Now we just need to fill in concatand filter_out_t. The latter is mainly glorified concat:
template <class... > struct concat;
template <> struct concat<> { using type = typelist<>; };
template <class... Ts>
struct concat<typelist<Ts...>> {
using type = typelist<Ts...>;
};
template <class... Ts, class... Us, class... Args>
struct concat<typelist<Ts...>, typelist<Us...>, Args...>
: concat<typelist<Ts..., Us...>, Args...>
{ };
template <class T, class TL>
struct filter_out;
template <class T, class TL>
using filter_out_t = typename filter_out<T, TL>::type;
template <class T, class... Ts>
struct filter_out<T, typelist<Ts...>>
: concat<
std::conditional_t<std::is_same<T, Ts>::value, typelist<>, typelist<Ts>>...
>
{ };
Now, given the list of types, we can define unique ones. To back up the original problem, we just need a size metafile:
template <size_t N>
using size_t_ = std::integral_constant<size_t, N>;
template <class > struct length;
template <class T> using length_t = typename length<T>::type;
template <class... Ts>
struct length<typelist<Ts...>>
: size_t_<sizeof...(Ts)>
{ };
And then wrap everything in one alias:
template <size_t... Ns>
using no_of_uniques = length_t<uniq_t<typelist<size_t_<Ns>...>>>;
Barry source
share