0

The result that i am trying to achieve is:

removeduplicates<TMPArray<8, 8, 9, 9, 10, 11, 11>>::type results in the same type as TMPArray<8, 9, 10, 11>

So far my solution looks like this:


template<int... I>
struct TMPArray {};

template <typename Arr1, typename Arr2>
struct concat;

template <int Ts, int... Us>
struct concat<TMPArray<Ts>, TMPArray<Us...>>
{
    using type = TMPArray<Ts, Us...>; 
};

template <int... Ts, int... Us>
struct concat<TMPArray<Ts...>, TMPArray<Us...>>
{
    using type = TMPArray<Ts..., Us...>;
};

template<typename TMPArray>
struct removeduplicates;

template<bool isSame, typename TMPArray>
struct makeremoveduplicates;

template<int Head, int Sec, int... Tail>
struct removeduplicates<TMPArray<Head, Sec, Tail...>> {
    using type = makeremoveduplicates<Head == Sec, TMPArray<Head, Sec, Tail...>>;
};

template<int Head, int Sec, int Third, int... Tail>
struct makeremoveduplicates<false, TMPArray<Head, Sec, Third, Tail...>> {
    using type = concat<TMPArray<Head>,makeremoveduplicates<Sec == Third,TMPArray<Sec, Third, Tail... >>::type>::type;
};

template<int Head, int Sec, int Third, int... Tail>
struct makeremoveduplicates<true, TMPArray<Head, Sec, Third, Tail...>> {
    using type = makeremoveduplicates<Sec == Third, TMPArray<Sec, Third, Tail... >>::type;
};

template<int Head, int Sec>
struct makeremoveduplicates<true, TMPArray<Head, Sec>> {
    using type = TMPArray<Head>;
};
 
template<int Head, int Sec>
struct makeremoveduplicates<false, TMPArray<Head, Sec>> {
    using type = TMPArray<Head, Sec>;
};

The idea behind this solution is that i am using the helper makeremoveduplicates to compare the first two elements and call the specialised template for when they match or don't match. This will append the result recursively using the concat metafunction.

I encounter a compilation error which states that:

Error   C2923   'concat': 'makeremoveduplicates<Sec==Third,TMPArray<Sec,Third,Tail...>>::type' is not a valid template type argument for parameter 'Arr2'

I would expect makeremoveduplicates type to evaluate to TMPArray, as per the base case:

template<int Head, int Sec>
struct makeremoveduplicates<true/false, TMPArray<Head, Sec>>

and the result of concat:

template <int Ts, int... Us>
struct concat<TMPArray<Ts>, TMPArray<Us...>>
{
    using type = TMPArray<Ts, Us...>; 
};

Why is this not a valid type?

wclifton
  • 3
  • 2

1 Answers1

1

The problem I see is that, in three points of your code, you have to add a typename to say the compiler that whats follows is a typename.

I hope this answer can explain why.

You have to add two typename here

template<int Head, int Sec, int Third, int... Tail>
struct makeremoveduplicates<false, TMPArray<Head, Sec, Third, Tail...>> {
    // ..........VVVVVVVV........................VVVVVVVV
    using type = typename concat<TMPArray<Head>, typename makeremoveduplicates<Sec == Third,TMPArray<Sec, Third, Tail... >>::type>::type;
};

and one here

template<int Head, int Sec, int Third, int... Tail>
struct makeremoveduplicates<true, TMPArray<Head, Sec, Third, Tail...>> {
    // ..........VVVVVVVV
    using type = typename makeremoveduplicates<Sec == Third, TMPArray<Sec, Third, Tail... >>::type;
};
max66
  • 65,235
  • 10
  • 71
  • 111
  • One more question on the usage: static_assert(std::is_same>::type, TMPArray<8, 9, 10, 11>>, ""); doesn't work as it says that i cant use it as a type? – wclifton Aug 11 '20 at 15:45
  • @wclifton - To be honest... no, I can't explain it. The rules that define when a `typename` is mandatory and when it isn't are too complicated for me. – max66 Aug 11 '20 at 19:29