Variant with unique types

Viewed 278

While writing a cpp library I ended up with possiblity that std::variants shall contain repeating types, that is for example, std::variant<int, double, int, std::string, int>. It may be useful in some occasions but in case of my library I find this unnecessary. And so I would like to filter type reptitions like this:

std::variant<int, double, int, std::string, int> -> std::variant<int, double, std::string>

std::variant<std::string, std::string, int> -> std::variant<std::string, int>

How can this be done?

2 Answers
#include <type_traits>
#include <variant>

template <typename T, typename... Ts>
struct filter_duplicates { using type = T; };

template <template <typename...> class C, typename... Ts, typename U, typename... Us>
struct filter_duplicates<C<Ts...>, U, Us...>
    : std::conditional_t<(std::is_same_v<U, Ts> || ...)
                       , filter_duplicates<C<Ts...>, Us...>
                       , filter_duplicates<C<Ts..., U>, Us...>> {};

template <typename T>
struct unique_variant;

template <typename... Ts>
struct unique_variant<std::variant<Ts...>> : filter_duplicates<std::variant<>, Ts...> {};

template <typename T>
using unique_variant_t = typename unique_variant<T>::type;

DEMO

With Boost.Mp11, this is a short one-liner (as always):

using V1 = mp_unique<std::variant<int, double, int, std::string, int>>;
// V1 is std::variant<int, double, std::string>

using V2 = mp_unique<std::variant<std::string, std::string, int>>;
// V2 is std::variant<std::string, int>
Related