Получить функцию арности из параметра шаблона
Как я могу получить арность произвольного типа функции, используемого в качестве параметра шаблона?
Функция может быть нормальной функцией, лямбда или функтором. Пример:
template<typename TFunc>
std::size_t getArity()
{
// ...?
}
template<typename TFunc>
void printArity(TFunc mFunc)
{
std::cout << "arity: " << getArity<TFunc>() << std::endl;
}
void testFunc(int) { }
int main()
{
printArity([](){}); // prints 0
printArity([&](int x, float y){}); // prints 2
printArity(testFunc); // prints 1
}
У меня есть доступ ко всем функциям C++14.
Нужно ли создавать специализацию для каждого типа функции (и всех соответствующих классификаторов)? Или есть более простой способ?
2 ответа
Решение
Предполагая, что все operator()
и функции, о которых мы говорим, не являются шаблонами или перегружены:
template <typename T>
struct get_arity : get_arity<decltype(&T::operator())> {};
template <typename R, typename... Args>
struct get_arity<R(*)(Args...)> : std::integral_constant<unsigned, sizeof...(Args)> {};
// Possibly add specialization for variadic functions
// Member functions:
template <typename R, typename C, typename... Args>
struct get_arity<R(C::*)(Args...)> :
std::integral_constant<unsigned, sizeof...(Args)> {};
template <typename R, typename C, typename... Args>
struct get_arity<R(C::*)(Args...) const> :
std::integral_constant<unsigned, sizeof...(Args)> {};
// Add all combinations of variadic/non-variadic, cv-qualifiers and ref-qualifiers
Спустя годы, но смотрите мое полное (бесплатное) решение здесь (производственный уровень, полностью документированный). В вашем случае вам нужен вспомогательный шаблон «ArgCount_v» (полностью описанный в ссылке выше). Применение его к собственному коду (отображает ожидаемые результаты — см. здесь ):
#include <iostream>
// See https://github.com/HexadigmSystems/FunctionTraits
#include "TypeTraits.h"
template<typename TFunc>
void printArity(TFunc mFunc)
{
////////////////////////////////////////////////
// Everything in "TypeTraits.h" above declared
// in this namespace
////////////////////////////////////////////////
using namespace StdExt;
/////////////////////////////////////////////////////
// Note: "tcout" (declared in "TypeTraits.h" above)
// always resolves to "std::cout" on non-Microsoft
// platforms and usually "std::wcout" on Microsoft
// platforms (when compiling for UTF-16 in that
// environment which is usually the case). You can
// directly call "std::cout" or "std::wcout" instead
// if you prefer, assuming you know which platform
// you're always running on.
/////////////////////////////////////////////////////
tcout << "arity: " << ArgCount_v<TFunc> << std::endl;
}
void testFunc(int) { }
int main()
{
printArity([](){}); // prints 0
printArity([&](int x, float y){}); // prints 2
printArity(testFunc); // prints 1
return 0;
}