c++templatesc++11variadic-templates

Ensuring that a variadic template contains no duplicates


I guess my whole problem is well described in the title. I am trying to create a variadic class template (in C++11, C++14 or C++1z).

template<typename ...Types> struct MyVariadicTemplate {};

and make sure that the list of types in any instantiation of MyVariadicTemplate is injective, so if I, for instance, call the following piece of code:

MyVariadicTemplate<int, double, int> x;

it won't compile (I'd be happy to do that somehow using static_assert).

I would appreciate a hint.


Solution

  • This can be written with the help of two metafunctions.

    First, IsContained checks whether a type appears in a type list.

    template <typename T, typename... List>
    struct IsContained;
    
    template <typename T, typename Head, typename... Tail>
    struct IsContained<T, Head, Tail...>
    {
        enum { value = std::is_same<T, Head>::value || IsContained<T, Tail...>::value };
    };
    
    template <typename T>
    struct IsContained<T>
    {
        enum { value = false };
    };
    

    Second, IsUnique checks whether a type list contains no duplicates. It uses IsContained to check all element combinations.

    template <typename... List>
    struct IsUnique;
    
    template <typename Head, typename... Tail>
    struct IsUnique<Head, Tail...>
    {
        enum { value = !IsContained<Head, Tail...>::value && IsUnique<Tail...>::value };
    };
    
    template <>
    struct IsUnique<>
    {
        enum { value = true };
    };
    

    With these tools, the static assertion is then very simple:

    template <typename... Ts>
    struct NoDuplicates
    {
        static_assert(IsUnique<Ts...>::value, "No duplicate types allowed");
    };