Given a type definition of a function, is there a way to cast the parameters received through a variadic template as an argument, to the exact types of the typedef
ed function?
#include <concepts>
#include <iostream>
typedef int foo(int, int);
template <typename func, typename... Args>
requires std::invocable<func, Args &&...>
void bar(Args&&... args) {
((std::cout << std::forward<Args>(args)), ...);
}
int main() { bar<foo>(4, 4.1); }
In this example I check if func
would be invocable with given arguments, then print the arguments that were passed. 4 and 4.1 get printed(as expected). But foo
accepts int,int
so the goal would be to print 4 and 4 as a result of converting args
to types of parameters accepted by foo
. A simple, yet functional solution would be greatly appreciated.
You might use template function/lambda to extract parameters of func
, as follow:
template <typename func, typename... Ts>
requires std::invocable<func, Ts&&...>
void bar(Ts&&... args) {
[&]<typename R, typename... Args>(std::type_identity<R(Args...)>){
((std::cout << std::forward<Args>(args)), ...);
}(std::type_identity<func>{});
}
As it seems conversion should be more "permissive",
you might replace std::forward
by static_cast
in some case:
template <typename TO, typename T>
decltype(auto) To(T&& t)
{
if constexpr (std::is_same_v<std::decay_t<TO>, std::decay_t<T>>) {
return std::forward<TO>(t);
} else {
return static_cast<TO>(t);
}
}
template <typename func, typename... Ts>
requires std::invocable<func, Ts&&...>
void bar(Ts&&... args) {
[&]<typename R, typename... Args>(std::type_identity<R(Args...)>){
((std::cout << To<Args>(args)), ...);
}(std::type_identity<func>{});
}