前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >apply,解决元组传参的利器

apply,解决元组传参的利器

作者头像
程序员的园
发布2024-07-18 13:30:48
120
发布2024-07-18 13:30:48
举报
文章被收录于专栏:程序员的园——原创文章

在C++中,当需要将一个元组的所有元素作为函数的实参时,可以使用可变参数模板和递归来实现一个解包函数。但是这不仅增加了代码的复杂度,也增加了编译时间。基于此,C++17引入std::apply,可以方便的将元组作为参数传递给函数。

std::apply的函数签名如下:

代码语言:javascript
复制
template <class_Callable, class_Tuple>
constexpr decltype(auto) apply(_Callable&& _Obj, 
                              _Tuple&& _Tpl) noexcept

其中_obj为可调用体,_Tpl为元组。由此可知apply存在可调用体和元组两部分。

apply的可调用体

在C++中可调用体的类型较多,可以是函数、模板,还可以是lambda表达式等

1. 函数

代码语言:javascript
复制
int add(int a, int b)
{
return a+b;
}


void using_apply_with_function()
{
std::tuple<int,int> tuple = {3,4};

int ret = std::apply(add, tuple);
std::cout<<"add with function is result is "<<ret<<"\n";
}

2. 模板

代码语言:javascript
复制
template<typenameT>
concept con_add = requires(T a, T b)
{
    {a+b}->std::same_as<T>;
};


//结合c++20 concept
template<con_addT>
Ttemplate_add(T a, T b)
{
    return a+b;
}


void using_apply_with_template()
{
    auto ret = std::apply(template_add<int>, std::make_tuple(30,40));
    std::cout << "add with template is result is " << ret << "\n";
}

3. lambda

代码语言:javascript
复制
void using_apply_with_lambda()
{
    auto f  = [](int a, int b,int c)->int{
        returna+b+c;
    };


    std::tuple<int,int,int>par{3,5,6};
    autoret=std::apply(f,par);
    std::cout<<"addwithlambdaisresultis"<<ret<<"\n";
}

4. std::functional

代码语言:javascript
复制
void using_apply_with_functional()
{
    std::function<int(int,int,int)> f = [](int a, int b, int c)->int {
        return a + b + c;
        };


    std::tuple<int, int, int > par{ 3,5,6 };
    auto ret = std::apply(f, par);
    std::cout << "add with functional is result is " << ret << "\n";
}

5. 函数对象

代码语言:javascript
复制
class DD {
public:
    void operator()(int a, int b)
    {
        std::cout<<a<<"+"<<b<<"="<<a+b<<"\n";
    }
};


void using_apply_with_obj()
{
    DD dd;
    std::tuple<int, int> par{9,10};
    std::apply(dd,par);
}

6. 可变参数模板

代码语言:javascript
复制
// 使用参数包计算参数的总和
template<typename... Args>
auto sum(Args... args) {
    return (args + ...);
}


void using_apply_with_variable_par() {
    auto p = std::make_tuple<int, int, int>(1, 20, 50);
    auto ret = std::apply([](auto... args) { returnsum(args...); }, p);
    std::cout << "add with variable par is result is " << ret << "\n";


    auto p1 = std::make_tuple<int, int, int>(1, 20, 50,80);
    ret = std::apply([](auto... args) { returnsum(args...); }, p1);
    std::cout << "add with variable par is result is " << ret << "\n";
}

apply的元组

apply的元组并不仅仅局限于std::tuple,不仅可以是tuple,还可以是array,还可以是pair

代码语言:javascript
复制
void using_apply_different_tuple()
{
    //tuple
    std::tuple<int, int> tuple = { 3,4 };
    int ret = std::apply(add, tuple);
    std::cout << "add with tuple is result is " << ret << "\n";


    //array
    std::array<int, 2> arr{ 1,6 };
    ret = std::apply(add, arr);
    std::cout << "add with array is result is " << ret << "\n";


    //pair
    ret = std::apply(add, std::pair(1, 6));
    std::cout << "add with pair is result is " << ret << "\n";
}

注意

在使用apply时,请注意元组中元素的数量必须和可调用体的形参数量一致,或参数个数可以是任意个,否则将出现编译错误。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-04-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员的园 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档