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?
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.