Search code examples
c++c++11variadic-templatesstatic-assertservice-locator

How can you statically check that a type T exists in a variadic template parameter list


I am trying to statically check to see if a type exists in a variadic template parameter list. However, this template list actually exists within a class that is passed a single type. The answer here shows how to check a list of parameters or a parameter pack, but I am unsure how to test a class that contains variadic templates.

For example

template <typename ...S>
class Services {};

template <typename Services>
class ServiceLocator
{
public:
      template <typename T>
      T& Resolve() 
      { 
           static_assert( check_t_exists_in_variadic_template_within_Services );
           return Find<T>();  
      }

};

What could I write in this static_assert to ensure that each call to this service locator is checked and a compiler error thrown if Resolve is called with a type that does not exist in the template parameter list inside Services?

What I am specicially after is something along the lines of:

static_assert(is_any<T,Services::S...>::value, "T does not exist in Services::S");

Solution

  • Here is a method using constexpr:

    #include <type_traits>
    
    template <typename T>
    constexpr bool contains() {
        return false;
    }
    
    template <typename T, typename A, typename... Tail>
    constexpr bool contains() {
        return std::is_same<T, A>::value ? true : contains<T, Tail...>();
    }
    
    int main()
    {
        // usage: contains<type_you_want_to_check, type_1, type_2,...>()
        static_assert(contains<float, int, double, float>(), "does contain float");
        static_assert(contains<float, int, double, char>(), "does not contain float");
    }
    

    Aside from being simpler and easier to understand (IMO), this method has the advantage of being easily extensible to other needs, as you can replace the std::is_same call with any other constexpr bool expression, such as std::is_base_of in order to check if the parameter pack contains any base or derived types.