Count the number of arguments in a lambda

  • A+
Category:Languages

I need to know the exact number of arguments that a lambda has. I do not care for their types, I just need a count.

auto lambda0 = [&]() { ... }; auto lambda1 = [&](int32_t a) { ... }; auto lambda2 = [&](int32_t a, auto b) { ... };  lambda_details<decltype(lambda0)>::argument_count; // Equals 0 lambda_details<decltype(lambda1)>::argument_count; // Equals 1 lambda_details<decltype(lambda2)>::argument_count; // Equals 2 

Detecting variadic lambdas would also be nice so that I can deal with that edge case as well.

auto lambda_variadic = [&](auto... args){ ... };  lambda_details<decltype(lambda_variadic)>::is_variadic; // Equals true 

How can I get this information?

 


You can create an object that can go into any parameter by overloading conversion operator. From there just test if the lambda is callable with a given number of such arguments, counting down from some arbitrary large number. If the lambda happens to be callable on the first try (with given arbitrary large number of arguments), we can assume it is variadic:

#include <iostream> #include <utility> #include <type_traits>   struct any_argument {     template <typename T>     operator T&&() const; };   template <typename Lambda, typename Is, typename = void> struct can_accept_impl : std::false_type {};  template <typename Lambda, std::size_t ...Is> struct can_accept_impl<Lambda, std::index_sequence<Is...>,                         decltype(std::declval<Lambda>()(((void)Is, any_argument{})...), void())> : std::true_type {};  template <typename Lambda, std::size_t N> struct can_accept : can_accept_impl<Lambda, std::make_index_sequence<N>> {};   template <typename Lambda, std::size_t Max, std::size_t N, typename = void> struct lambda_details_impl : lambda_details_impl<Lambda, Max, N - 1> {};  template <typename Lambda, std::size_t Max, std::size_t N> struct lambda_details_impl<Lambda, Max, N, std::enable_if_t<can_accept<Lambda, N>::value>> {     static constexpr bool is_variadic = (N == Max);     static constexpr std::size_t argument_count = N; };  template <typename Lambda, std::size_t Max = 50> struct lambda_details : lambda_details_impl<Lambda, Max, Max> {};   int main() {     auto lambda0 = []() {};     auto lambda1 = [](int a) {};     auto lambda2 = [](int a, auto b) {};     auto lambda3 = [](int a, auto b, char = 'a') {};     auto lambda4 = [](int a, auto b, char = 'a', auto...) {};      std::cout << lambda_details<decltype(lambda0)>::is_variadic << " " << lambda_details<decltype(lambda0)>::argument_count << "/n"; // 0 0     std::cout << lambda_details<decltype(lambda1)>::is_variadic << " " << lambda_details<decltype(lambda1)>::argument_count << "/n"; // 0 1     std::cout << lambda_details<decltype(lambda2)>::is_variadic << " " << lambda_details<decltype(lambda2)>::argument_count << "/n"; // 0 2     std::cout << lambda_details<decltype(lambda3)>::is_variadic << " " << lambda_details<decltype(lambda3)>::argument_count << "/n"; // 0 3     std::cout << lambda_details<decltype(lambda4)>::is_variadic << " " << lambda_details<decltype(lambda4)>::argument_count << "/n"; // 1 50 } 

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: