Search code examples
c++templatesc++11static-assert

Narrow down allowed types in templated using type alias with static_assert


While still learning template based meta programming, I've come to the following problem: I've got a templated using type alias, and I want to narrow down the allowed types with static_assert but I'm not sure how to write it:

using service_func_plain_loop_t = std::function<void(void)>;
using service_func_with_arg_loop_t = std::function<void(std::string)>;
using service_callbacks_t = std::map<event, std::function<bool(void) >>;

template<typename service_loop> using service_functionality_t =
std::pair<service_loop, service_callbacks_t>;
static_assert(
        std::is_convertible<service_loop,service_func_plain_loop_t>.value ||
        std::is_convertible<service_loop,service_func_with_arg_loop_t>.value,
        "service_loop has to be either service_func_plain_loop_t or " 
        "service_func_with_arg_loop_t");

This approach fails because of service_loop is not declared in the scope of static_assert. When checking classes I can just move the assert into the class scope, but what's the syntax here?


Solution

  • You could write a helper class to do the static_assert:

    template <typename service_loop>
    struct service_functionality {
        static_assert(
            std::is_convertible<service_loop,service_func_plain_loop_t>::value ||
            std::is_convertible<service_loop,service_func_with_arg_loop_t>::value,
            "service_loop has to be either service_func_plain_loop_t or " 
            "service_func_with_arg_loop_t");
    
        using type = std::pair<service_loop, service_callbacks_t>;   
    };
    
    template<typename service_loop> using service_functionality_t =
    typename service_functionality<service_loop>::type;
    

    Note also that it should be std::is_convertible<T,U>::value or std::is_convertible<T,U>{} rather than std::is_convertible<T,U>.value. Although we'll likely get std::is_convertible_v<T,U> helper variable templates in C++17.

    Live Demo