I have a meta function which gives me the type of the I
-th argument of a lambda/function:
#include <iostream>
#include <tuple>
namespace details
{
//! Spezialization for Funktion-Pointers
template<typename Ret, typename... Args>
std::tuple<Args...> getArgs(Ret (*)(Args...));
//! Spezialization for Functor/Lambdas
template<typename F, typename Ret, typename... Args>
std::tuple<Args...> getArgs(Ret (F::*)(Args...));
//! Spezialization for Functor/Lambdas
template<typename F, typename Ret, typename... Args>
std::tuple<Args...> getArgs(Ret (F::*)(Args...) const);
}; // namespace details
template<typename F, std::size_t I>
using GetArg = std::tuple_element_t<I, decltype(details::getArgs(std::declval<F>()))>;
int main()
{
auto f1 = [](int a, int b){};
static_assert(std::is_same<GetArg<decltype(f1), 0>, int>{}, "Not the same!");
// auto f2 = [](int a, auto b){};
// static_assert(std::is_same<GetArg<decltype(f2), 0>, int>{}, "Not the same!");
}
The second lambda with auto
specifier does not compile as my spezializations are not matched, because auto
is like a template parameter T
, which is not known.
Is there a way of making this work for f2
as well?
Since the lambda is an opaque type and a template function has no type unless instantiated with template argument types, I have not really any idea of how to make this work? Is it impossible?
I think you miss this:
template <typename F>
decltype(getArgs(&F::operator())) getArgs(F);
So final version would be:
namespace details
{
//! Spezialization for Funktion-Pointers
template <typename Ret, typename... Args>
std::tuple<Args...> getArgs(Ret (*)(Args...));
//! Spezialization for Functor/Lambdas
template <typename F, typename Ret, typename... Args>
std::tuple<Args...> getArgs(Ret (F::*)(Args...));
//! Spezialization for Functor/Lambdas
template <typename F, typename Ret, typename... Args>
std::tuple<Args...> getArgs(Ret (F::*)(Args...) const);
template <typename F>
decltype(getArgs(&F::operator())) getArgs(F);
}; // namespace details
template <typename F, std::size_t I>
using GetArg = std::tuple_element_t<I, decltype(details::getArgs(std::declval<F>()))>;
Now it compiles: https://godbolt.org/z/r1PsE36Wx