Skip to content

Instantly share code, notes, and snippets.

@rbock
Created November 16, 2014 21:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rbock/ad8eedde80c060132a18 to your computer and use it in GitHub Desktop.
Save rbock/ad8eedde80c060132a18 to your computer and use it in GitHub Desktop.
Test if parameter pack arguments are unique
// This algorithm to determine if the parameter pack arguments are unique looks linear.
// It turns out to be quadratic anyway (something inside the compiler, I guess)
#include <utility>
template<typename T>
struct empty{};
template<typename... Ts>
struct unique;
template<>
struct unique<>
{
static constexpr bool value = true;
};
template<typename T, typename... Ts>
struct unique<T, Ts...>: public unique<Ts...>, public empty<T>
{
using base = unique<Ts...>;
static constexpr bool value = base::value and not std::is_base_of<empty<T>, base>::value;
};
template<std::size_t>
struct A{};
template<std::size_t ...Is>
void test(const std::integer_sequence<std::size_t, Is...>&)
{
static_assert(unique<A<Is>...>::value, "");
static_assert(not unique<A<Is>..., A<0>>::value, "");
}
int main()
{
test(std::make_index_sequence<100>{});
}
// This version is almost a factor two faster by always handling two parameters at once
// It seems to indicate that there might be some divide and conquer trick but I don't see it yet
#include <utility>
template<typename T>
struct empty{};
template<bool, typename... Ts>
struct base_if {};
template<typename... Ts>
struct base_if<true, Ts...>: public empty<Ts>...
{};
template<typename... Ts>
struct unique;
template<>
struct unique<>
{
static constexpr bool value = true;
};
template<typename T>
struct unique<T>: public empty<T>
{
static constexpr bool value = true;
};
template<typename T0, typename T1, typename... Ts>
struct unique<T0, T1, Ts...>: public unique<Ts...>, public base_if<not std::is_same<T0, T1>::value, T0, T1>
{
using base = unique<Ts...>;
static constexpr bool value = base::value
and not std::is_same<T0, T1>::value
and not std::is_base_of<empty<T0>, base>::value
and not std::is_base_of<empty<T1>, base>::value
;
};
template<std::size_t>
struct A{};
template<std::size_t ...Is>
void test(const std::integer_sequence<std::size_t, Is...>&)
{
static_assert(unique<A<Is>...>::value, "");
static_assert(not unique<A<Is>..., A<0>>::value, "");
}
int main()
{
test(std::make_index_sequence<1>{});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment