RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 759109
Accepted
абвгд
абвгд
Asked:2020-12-16 18:38:41 +0000 UTC2020-12-16 18:38:41 +0000 UTC 2020-12-16 18:38:41 +0000 UTC

n个变量的函数声明

  • 772

有一个号码n。如何声明n同类型变量的函数?情况是这样的:

using my_type = int;
constexpr size_t n = 4;

std::function<void(give_me_n_types<my_type>(n))> my_func;
c++
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Best Answer
    Croessmah stands with Russia
    2020-12-16T19:12:42Z2020-12-16T19:12:42Z

    想到的第一件事:

    #include <iostream>
    #include <utility>
    #include <functional>
    
    
    namespace details
    {
        template<typename T, ::std::size_t = 0>
        using get_type_t = T;  
    
        template<typename RetType, typename ArgsType, ::std::size_t ... I>
        auto make_function_type_impl(::std::index_sequence<I...>) -> RetType (&)(get_type_t<ArgsType, I>...);
    
        template<typename RetType, typename ArgsType, ::std::size_t N>
        using make_function_type = std::remove_reference_t<decltype(make_function_type_impl<RetType, ArgsType>(::std::make_index_sequence<N>()))>;
    }//namespace details
    
    
    
    template<typename RetType, typename ArgsType, ::std::size_t N>
    using make_function_type_n = ::details::make_function_type<RetType, ArgsType, N>;
    
    
    double foo(int x, int y)
    {
        return (double)x/y;
    }
    
    
    int main()
    {
        using my_type = int;
        constexpr size_t n = 2;
    
        std::function<make_function_type_n<double, my_type, n>> my_func = foo;
    
        std::cout << my_func(10, 4);
    }
    

    http://rextester.com/CPMS17471

    它的工作原理如下。

    make_function_type_n<double, int, 2>
    

    使用的模板扩展为:

    ::details::make_function_type<double, int, 2>
    

    反过来,这个模板使用扩展为

    std::remove_reference_t<decltype(make_function_type_impl<double, int>(::std::make_index_sequence<2>()))>; 
    

    ::std::make_index_sequence<2>()将创建一个类型的对象

    std::index_sequence<0, 1>// где 0 и 1 - это индексы до 2.
    

    那些。我们在 decltype 中有一个表达式

    make_function_type_impl<double, int>(::std::index_sequence<0, 1>)
    

    因此,我们得到以下信息:

    make_function_type_impl(::std::index_sequence<0, 1>) -> double (&)(get_type_t<int, 0>, get_type_t<int, 1>)
    

    所以 decltype 会给出一个类型函数double(int, int)的引用,并用 std::remove_reference_t 删除该引用。

    在写作时,出现了重复不是一个参数,而是几个参数的想法。

    首先,您需要一个结构来存储所需的函数类型并增加其参数。

    namespace details
    {
        template<typename RetType, typename ... Params>
        struct func_n_t {
            using type = RetType(Params...);//Тип функции
            //Этот шаблонный using будет хранить тип func_n_t с параметрами, добавленными к текущим
            template<typename ... Args>
            using add = func_n_t<RetType, Params..., Args...>;
        };
    

    剩下要做的就是创建一个参数重复 N 次的 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<N - 1, typename Func::template add<Args...>, Args...>::type;        
        };
        //Частичная специализация, которая остановит рекурсию
        template<typename Func, typename ... Args>
        struct function_n_t_impl<0, Func, Args...>
        {
            //Просто берем от типа Func тип нужной нам функции
            using type = typename Func::type;   
        };
    }//namespace details
    
    //Псевдоним, который запускает формирование нужного типа, начиная с func_n_t<RetType> (т.е. с type = RetType())
    template<::std::size_t N, typename RetType, typename ... ArgsType>
    using make_function_t = typename ::details::function_n_t_impl<N, details::func_n_t<RetType>, ArgsType...>::type;
    

    用法:

    //Указатель на функцию, возвращающую double и принимающую два параметра типа int
    make_function_t<2, double, int>* my_foo = foo;
    

    完整代码:

    #include <iostream>
    #include <functional>
    
    
    namespace details
    {
        template<typename RetType, typename ... Params>
        struct func_n_t {
            using type = RetType(Params...);//Тип функции
            //Этот шаблонный using будет хранить тип func_n_t с параметрами, добавленными к текущим
            template<typename ... Args>
            using add = func_n_t<RetType, Params..., Args...>;
        };  
    
    
        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<N - 1, typename Func::template add<Args...>, Args...>::type;        
        };
        //Частичная специализация, которая остановит рекурсию
        template<typename Func, typename ... Args>
        struct function_n_t_impl<0, Func, Args...>
        {
            //Просто берем от типа Func тип нужной нам функции
            using type = typename Func::type;   
        };
    }//namespace details
    
    
    //Псевдоним, который запускает формирование нужного типа, начиная с func_n_t<RetType> (т.е. с type = RetType())
    template<::std::size_t N, typename RetType, typename ... ArgsType>
    using make_function_t = typename ::details::function_n_t_impl<N, details::func_n_t<RetType>, ArgsType...>::type;
    
    
    //Функции для теста
    double foo(int x, int y)
    {
        std::cout << "foo(" << x << ", " << y << ")\n";
        return (double)x/y;
    }
    
    
    double bar(int x1, double y1, int x2, double y2)
    {
        std::cout << "bar(" << x1 << ", " << y1 << ", " << x2 << ", " << y2 << ")\n";
        return x1/y1 + x2/y2;
    }
    
    
    void zoo()
    {
        std::cout << "zoo\n";
    }
    
    
    int main()
    {
        //Функция, возвращающая double и принимающая два параметра типа int
        make_function_t<2, double, int>* my_foo = foo;
        //Функция, возвращающая double и принимающая четыре параметра: int double, int double
        //Набор параметров int, double повторяется два раза.
        std::function<make_function_t<2, double, int, double>> my_bar = bar;
        //Функции, возвращающие void и не принимающие параметров
        std::function<make_function_t<10, void>> my_zoo1 = zoo;//10 пустых наборов
        std::function<make_function_t<0, void, int, size_t, void>> 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

    • 19
  2. user7860670
    2020-12-16T22:07:09Z2020-12-16T22:07:09Z

    您可以写得更短一些,而不使用标准库并保留在 C ++ 11 的框架内:

    template<typename TResult, typename TArg, int remaining_args_count, typename... TArgs> class
    t_n_args_fun_impl final
    {
        public: using t_fun = typename t_n_args_fun_impl<TResult, TArg, remaining_args_count - 1, TArgs..., TArg>::t_fun;
    };
    
    template<typename TResult, typename TArg, typename... TArgs> class
    t_n_args_fun_impl<TResult, TArg, 0, TArgs...> final
    {
        public: using t_fun = TResult (TArgs...);
    };
    
    template<typename TResult, typename TArg, int args_count> using
    t_n_args_fun = typename t_n_args_fun_impl<TResult, TArg, args_count>::t_fun;
    
    #include <functional>
    #include <type_traits>
    
    int main()
    {
        static_assert
        (
            ::std::is_same
            <
                ::std::function<t_n_args_fun<void, double, 5>>
            ,   ::std::function<void (double, double, double, double, double)>
            >::value
        ,   ""
        );
        static_assert
        (
            ::std::is_same
            <
                ::std::function<t_n_args_fun<void, void, 0>>
            ,   ::std::function<void (void)>
            >::value
        ,   ""
        );
        return(0);
    }
    

    在线编译器

    • 12

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    Python 3.6 - 安装 MySQL (Windows)

    • 1 个回答
  • Marko Smith

    C++ 编写程序“计算单个岛屿”。填充一个二维数组 12x12 0 和 1

    • 2 个回答
  • Marko Smith

    返回指针的函数

    • 1 个回答
  • Marko Smith

    我使用 django 管理面板添加图像,但它没有显示

    • 1 个回答
  • Marko Smith

    这些条目是什么意思,它们的完整等效项是什么样的

    • 2 个回答
  • Marko Smith

    浏览器仍然缓存文件数据

    • 1 个回答
  • Marko Smith

    在 Excel VBA 中激活工作表的问题

    • 3 个回答
  • Marko Smith

    为什么内置类型中包含复数而小数不包含?

    • 2 个回答
  • Marko Smith

    获得唯一途径

    • 3 个回答
  • Marko Smith

    告诉我一个像幻灯片一样创建滚动的库

    • 1 个回答
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Алексей Шиманский 如何以及通过什么方式来查找 Javascript 代码中的错误? 2020-08-03 00:21:37 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5