Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find number of unique values of a parameter pack

Given a parameter pack with variadic arguments, how can one find the number of unique values in the pack. I am looking for something along the lines of

no_of_uniques<0,1,2,1,2,2>::value // should return 3

My rudimentary implementation looks something this

template <size_t ... all>
struct no_of_uniques;
// this specialisation exceeds -ftemplate-depth as it has no terminating condition
template <size_t one, size_t ... all>
struct no_of_uniques<one,all...> {
    static const size_t value = no_of_uniques<one,all...>::value;
};
template <size_t one, size_t two, size_t three>
struct no_of_uniques<one,two,three> {
    static const size_t value = (one==two && one==three && two==three) ? 1:
                                (one!=two && two==three) ? 2:
                                (one==two && one!=three) ? 2:
                                (one==three && two!=three) ? 2: 3;
};
template <size_t one, size_t two>
struct no_of_uniques<one,two> {
    static const size_t value = one==two ? 1: 2;
};
template <size_t one>
struct no_of_uniques<one> {
    static const size_t value = 1;
};

Here, I have specialised for up to three arguments but understandably the code grows exponentially with the number of arguments. I would like to have a meta solution for this using solely STL and no third party libraries like Boost.MPL.

A similar question albeit in the context of checking unique types, rather than finding number of unique values of parameter pack can be found here:

Check variadic templates parameters for uniqueness

In the process of finding the number of unique values of a parameter pack, we might need to sort the pack first, and an excellent implementation of that is provided in this other question

Quick sort at compilation time using C++11 variadic templates

like image 845
romeric Avatar asked Dec 02 '22 13:12

romeric


1 Answers

Here's a simple O(n^2) way to do it

template <size_t...>
struct is_unique : std::integral_constant<bool, true> {};

template <size_t T, size_t U, size_t... VV>
struct is_unique<T, U, VV...> : std::integral_constant<bool, T != U && is_unique<T, VV...>::value> {};

template <size_t...>
struct no_unique : std::integral_constant<size_t, 0> {};

template <size_t T, size_t... UU>
struct no_unique<T, UU...> : std::integral_constant<size_t, is_unique<T, UU...>::value + no_unique<UU...>::value> {};

So using your example:

no_unique<0, 1, 2, 1, 2, 2>::value; // gives 3
like image 103
kmdreko Avatar answered Dec 05 '22 07:12

kmdreko