I am writing player command handler for some game server. Handler is a some function which accepts arbitrary combination of arguments of allowed types. Allowed types are double, int, std::string, bool. I add new command handler dynamically using method template<typename F> void addCommand(string name, F handler);. But I need to restrict template type F to be:
- function/method/lambda
- types of arguments of that function should be in the list of allowed types.
I check that F is a function using following concept:
// Helper concept to check if a type is one of the allowed types
template <typename T, typename... AllowedTypes>
concept IsAllowedType = (std::is_same_v<AllowedTypes, T> || ...);
// Concept to check if a function satisfies the requirements
template <typename F, typename... AllowedArgTypes>
concept IsFunctionAndAcceptsAllowedTypes = requires {
std::invocable<F>;
// TODO check arg types of F
};
So, the question is, how to infer argument types of provided type F and check them against list of allowed types? I know I can use function_traits helper:
template <typename T>
struct function_traits;
template <typename R, typename... Args>
struct function_traits<std::function<R(Args...)>>
{
static const size_t nargs = sizeof...(Args);
typedef R result_type;
template <size_t i>
struct arg
{
typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
};
};
But I can't get my head around this: how to iterate over tuple types to check them in context of templates?
I think this is only possible by defining a helper that has an own requires call: