Call template function with one or two arguments?
I have situation when i create template function with one argument (component) and sometimes with two (component, gameObject).
template<typename Component, typename F>
static void CallFunction(GameObject gameObject, F func) {
// Note: UIFunction should has component as first param and/or gameObject second.
auto& component = gameObject.GetComponent<Component>();
constexpr std::size_t args = sizeof...(F);
if constexpr (args == 1)
func(component);
else
func(component, gameObject);
}
And i try to use constexpr std::size_t args = sizeof...(F);
to get size of arguments of my function and call it with one argument or two. But when im try to use this i get:
C2780 'auto CallFunction::<lambda_06a5858866216a23f9192bc2da910cdc>::operator ()(_T1 &,_T2) const': expects 2 arguments - 1 provided.
How do this properly because im not big fan of templates.
Im removed sizeof...(T)
and use std::is_invokable_v
for checking that func can be called with some count and type of arguments.
template<typename Component, typename F>
static void CallFunction(GameObject gameObject, F func) {
// Note: UIFunction should has component as first param and/or gameObject second.
auto& component = gameObject.GetComponent<Component>();
if constexpr (std::is_invocable_v<F, Component>)
func(component);
if constexpr (std::is_invocable_v<F, Component, GameObject>)
func(component, gameObject);
}
Since C++17 type traits can be used to determine whether the object is invocable accepting some argument types. Small example, change it as needed:
template<typename> inline constexpr bool wrong_func_v = false;
template<typename Component, typename F>
static void CallFunction(GameObject gameObject, F func)
{
auto& component = gameObject.GetComponent<Component>();
if constexpr (std::is_invocable_v<F, Component>)
func(component);
else if constexpr (std::is_invocable_v<F, Component, GameObject>)
func(component, gameObject);
else
static_assert(wrong_func_v<F>, "wrong param types/count");
}
Then we can use this template:
CallFunction<SomeComponent>(gameObject, one_arg_func);
CallFunction<OrAnotherComponent>(gameObject, two_arg_func);