Перейти к содержанию

Последнее обновление:2026-10-12

Интересный фрагмент C++-кода

0. Вступление

Цель: как узнать количество параметров у лямбды или функтора?

В этом разделе сделаем это с помощью шаблонов + ::* + decay + decltype!

1. Реализация

Итоговый эффект:

auto c1 = [](int x, double y) { return x * y; };
std::cout << argument_count<decltype(c1)>::value << std::endl;
MyClass f;
std::cout << argument_count<decltype(f)>::value << std::endl;
Вывод: 2

Подумаем над задачей — нужно понять несколько моментов:

  • как добраться до места, где находятся функтор и лямбда?
  • как получить количество параметров в сигнатуре этой функции?

Для первого вопроса можно использовать ::*, чтобы сослаться на объявление члена; и для функтора, и для лямбды это &std::decay<F>::type::operator()). Проще говоря, в обоих случаях мы получаем адрес объявления operator().

Здесь decay используется, чтобы снять cv-квалификаторы. Возьмём MyClass выше: сначала через std::decay<F>::type получаем тип MyClass, затем берём адрес соответствующего operator() и передаём его в argument_count_impl.

template <typename F>
using argument_count = decltype(argument_count_impl(&std::decay<F>::type::operator()));
Реализация argument_count_impl тоже довольно проста: с помощью сигнатуры R (F::*)(A...) получаем соответствующую функцию — здесь используются вариативные шаблоны, ::*, а sizeof применяется для получения количества параметров; integral_constant указывает, что этот константный тип компилятора — int со значением sizeof...(A).

template <typename F, typename R, typename... A>
static std::integral_constant<int, sizeof...(A)> argument_count_impl(R (F::*)(A...));
На этом основана реализация возможности получать количество параметров Lambda или Functor~

Похожие темы

Комментарии