Есть число n. Как объявить функцию n переменных одного типа? Ситуация примерно такая: using my_type = int constexpr size_t n = 4 std::function(n))> my_func
Ответ Первое, что пришло в голову: #include #include #include namespace details { template using get_type_t = T template auto make_function_type_impl(::std::index_sequence) -> RetType (&)(get_type_t...) template using make_function_type = std::remove_reference_t(::std::make_index_sequence()))> }//namespace details
template using make_function_type_n = ::details::make_function_type double foo(int x, int y) { return (double)x/y } int main() { using my_type = int constexpr size_t n = 2 std::function> my_func = foo std::cout << my_func(10, 4) } <br>http://rextester.com/CPMS17471 Работает это следующим образом. make_function_type_n Шаблонный using разворачивается в: ::details::make_function_type В свою очередь этот шаблонный using разворачивается в std::remove_reference_t(::std::make_index_sequence<2>()))> ::std::make_index_sequence<2>() создаст объект типа std::index_sequence<0, 1>// где 0 и 1 - это индексы до 2. т.е. у нас в decltype попадает выражение make_function_type_impl(::std::index_sequence<0, 1>) Следовательно, получаем следующее: make_function_type_impl(::std::index_sequence<0, 1>) -> double (&)(get_type_t, get_type_t) Таким образом decltype даст ссылку на функцию типа double(int, int), а ссылка удаляется с помощью std::remove_reference_t. Пока писал, возникла идея повторить не один параметр, а несколько. Для начала нужна будет структура, которая будет хранить нужный тип функции и наращивать его параметры. namespace details { template struct func_n_t { using type = RetType(Params...) //Тип функции //Этот шаблонный using будет хранить тип func_n_t с параметрами, добавленными к текущим template using add = func_n_t } Всё что остается сделать - создать func_n_t с повторенными N раз параметрами. template<::std::size_t N, typename Func, typename ... Args> struct function_n_t_impl { //Применяем рекурсию шаблонов. //На каждом шаге к инстансу шаблона func_n_t прибавляются аргументы Args //При этом N уменьшается на 1 using type = typename function_n_t_impl, Args...>::type } //Частичная специализация, которая остановит рекурсию template struct function_n_t_impl<0, Func, Args...> { //Просто берем от типа Func тип нужной нам функции using type = typename Func::type } }//namespace details //Псевдоним, который запускает формирование нужного типа, начиная с func_n_t (т.е. с type = RetType()) template<::std::size_t N, typename RetType, typename ... ArgsType> using make_function_t = typename ::details::function_n_t_impl, ArgsType...>::type Использование: //Указатель на функцию, возвращающую double и принимающую два параметра типа int make_function_t<2, double, int>* my_foo = foo Полный код: #include #include namespace details { template struct func_n_t { using type = RetType(Params...) //Тип функции //Этот шаблонный using будет хранить тип func_n_t с параметрами, добавленными к текущим template using add = func_n_t } template<::std::size_t N, typename Func, typename ... Args> struct function_n_t_impl { //Применяем рекурсию шаблонов. //На каждом шаге к инстансу шаблона func_n_t прибавляются аргументы Args //При этом N уменьшается на 1 using type = typename function_n_t_impl, Args...>::type } //Частичная специализация, которая остановит рекурсию template struct function_n_t_impl<0, Func, Args...> { //Просто берем от типа Func тип нужной нам функции using type = typename Func::type } }//namespace details //Псевдоним, который запускает формирование нужного типа, начиная с func_n_t (т.е. с type = RetType()) template<::std::size_t N, typename RetType, typename ... ArgsType> using make_function_t = typename ::details::function_n_t_impl, ArgsType...>::type //Функции для теста double foo(int x, int y) { std::cout << "foo(" << x << ", " << y << ")<br>" return (double)x/y } double bar(int x1, double y1, int x2, double y2) { std::cout << "bar(" << x1 << ", " << y1 << ", " << x2 << ", " << y2 << ")<br>" return x1/y1 + x2/y2 } void zoo() { std::cout << "zoo<br>" } int main() { //Функция, возвращающая double и принимающая два параметра типа int make_function_t<2, double, int>* my_foo = foo //Функция, возвращающая double и принимающая четыре параметра: int double, int double //Набор параметров int, double повторяется два раза. std::function> my_bar = bar //Функции, возвращающие void и не принимающие параметров std::function> my_zoo1 = zoo //10 пустых наборов std::function> my_zoo2 = zoo //0 наборов int, size_t, void my_foo(10, 4) my_bar(10, 4.6, 15, 5.3) my_zoo1() my_zoo2() } http://rextester.com/HWBJA2947