C++ 包装器,看这一篇就够了

C++ 包装器

1 简介

包装器用于给其他编程接口提供更一致或更合适的接口。

模板bind可替代bind1st和bind2nd,且更灵活

模板mem_fn让您能够将成员函数作为常规函数进行传递

模板reference_wrapper让您能够创建像引用但可被复制的对象

包装器function让您能够以统一的方式处理多种类似于函数的形式

模板function是在头文件functional头文件中声明的,他从参数和返回值的角度定义了一个对象,可用于包装调用参数和返回值相同的函数指针、伪函数或lambda表达式

2 为什么使用包装器

由于函数调用可以使用函数名、函数指针、函数对象或有名称的lambda表达式,可调用类型太丰富导致模板的效率极低。

包装器用于解决效率低的问题。

3 测试与对比

3.1 普通版本与优化版本

3.1.1 代码

somedefs.h

#pragma once

// somedefs.h

#include <iostream>

template <typename T, typename F>

T use_f(T v, F f)

{

    static int count = 0;

    count++;

    std::cout << " use_f count = " << count

        << ", &count = " << &count << std::endl;

    return f(v);

}

class Fp

{

private:

    double z_;

public:

    Fp(double z = 1.0) : z_(z) {}

    double operator()(double p) { return z_ * p; }

};

class Fq

{

private:

    double z_;

public:

    Fq(double z = 1.0) : z_(z) {}

    double operator()(double q) { return z_ + q; }

};

main.cpp

/*

Project name :          _2OWrappers

Last modified Date:     2022年5月6日10点09分

Last Version:           V1.0

Descriptions:           包装器

*/

#include "somedefs.h"

#include <iostream>

#include <functional>

double dub(double x) { return 2.0 * x; }

double square(double x) { return x * x; }

int main()

{

    using namespace std;

    double y = 1.21;

    //此处实例化了五个use_f模板函数,导致编译代码多,效率低

    cout << "普通版本******************************************************" << endl;

    cout << "Function pointer dub:\n";

    cout << " " << use_f(y, dub) << endl;

    cout << "Function pointer square:\n";

    cout << " " << use_f(y, square) << endl;

    cout << "Function object Fp:\n";

    cout << " " << use_f(y, Fp(5.0)) << endl;

    cout << "Function object Fq:\n";

    cout << " " << use_f(y, Fq(5.0)) << endl;

    cout << "Lambda expression 1:\n";

    cout << " " << use_f(y, [](double u) {return u * u; }) << endl;

    cout << "Lambda expression 2:\n";

    cout << " " << use_f(y, [](double u) {return u + u / 2.0; }) << endl;

    cout << "优化版本******************************************************" << endl;

    //考虑到上述函数的参数和返回值(call signature)都为 double(double),

    //因此使用function<double(double)>装饰它创建六个包装器,实现只实例化一个use_f函数模板

    function<double(double)> ef1 = dub;

    function<double(double)> ef2 = square;

    function<double(double)> ef3 = Fq(10.0);

    function<double(double)> ef4 = Fp(10.0);

    function<double(double)> ef5 = [](double u) {return u * u; };

    function<double(double)> ef6 = [](double u) {return u + u / 2.0; };

    cout << "Function pointer dub:\n";

    cout << " " << use_f(y, ef1) << endl;

    cout << "Function pointer square:\n";

    cout << " " << use_f(y, ef2) << endl;

    cout << "Function object Fp:\n";

    cout << " " << use_f(y, ef3) << endl;

    cout << "Function object Fq:\n";

    cout << " " << use_f(y, ef4) << endl;

    cout << "Lambda expression 1:\n";

    cout << " " << use_f(y, ef5) << endl;

    cout << "Lambda expression 2:\n";

    cout << " " << use_f(y, ef6) << endl;

 

    return 0;

}

3.1.2 运行结果

普通版本******************************************************

Function pointer dub:

 use_f count = 1, &count = 00007FF6DD7436D0

 2.42

Function pointer square:

 use_f count = 2, &count = 00007FF6DD7436D0

 1.4641

Function object Fp:

 use_f count = 1, &count = 00007FF6DD7436D4

 6.05

Function object Fq:

 use_f count = 1, &count = 00007FF6DD7436D8

 6.21

Lambda expression 1:

 use_f count = 1, &count = 00007FF6DD7436DC

 1.4641

Lambda expression 2:

 use_f count = 1, &count = 00007FF6DD7436E0

 1.815

优化版本******************************************************

Function pointer dub:

 use_f count = 1, &count = 00007FF6DD7436E8

 2.42

Function pointer square:

 use_f count = 2, &count = 00007FF6DD7436E8

 1.4641

Function object Fp:

 use_f count = 3, &count = 00007FF6DD7436E8

 11.21

Function object Fq:

 use_f count = 4, &count = 00007FF6DD7436E8

 12.1

Lambda expression 1:

 use_f count = 5, &count = 00007FF6DD7436E8

 1.4641

Lambda expression 2:

 use_f count = 6, &count = 00007FF6DD7436E8

 1.815

 

D:\Prj\_C++Self\_34Wrappers\x64\Debug\_34Wrappers.exe (进程 1132)已退出,代码为 0。

要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。

按任意键关闭此窗口. . .

3.2 最优化版本

3.2.1 代码

somedefs.h

#pragma once

#include <iostream>

#include <functional>

//使用function模板

template <typename T>

T use_f(T v, std::function<T(T)> f)

{

    static int count = 0;

    count++;

    std::cout << " use_f count = " << count

        << ", &count = " << &count << std::endl;

    return f(v);

}

class Fp

{

private:

    double z_;

public:

    Fp(double z = 1.0) : z_(z) {}

    double operator()(double p) { return z_ * p; }

};

class Fq

{

private:

    double z_;

public:

    Fq(double z = 1.0) : z_(z) {}

    double operator()(double q) { return z_ + q; }

};

main.cpp

/*

Project name :          _2OWrappers_optimization

Last modified Date:     2022年5月6日10点30分

Last Version:           V1.0

Descriptions:           包装器最优化

*/

#include "somedefs.h"

 

double dub(double x) { return 2.0 * x; }

double square(double x) { return x * x; }

int main()

{

    using namespace std;

    double y = 1.21;

    typedef function<double(double)> fdd; // simplify the type declaration

    cout << "Function pointer dub:\n";

    cout << use_f(y, fdd(dub)) << endl; // create and initialize object to dub

    cout << "Function pointer square:\n";

    cout << use_f(y, fdd(square)) << endl;

    cout << "Function object Fp:\n";

    cout << use_f(y, fdd(Fp(5.0))) << endl;

    cout << "Function object Fq:\n";

    cout << use_f(y, fdd(Fq(5.0))) << endl;

    cout << "Lambda expression 1:\n";

    cout << use_f(y, fdd([](double u) {return u * u; })) << endl;

    cout << "Lambda expression 2:\n";

    cout << use_f(y, fdd([](double u) {return u + u / 2.0; })) << endl;

    return 0;

}

3.2.2 运行结果

Function pointer dub:

 use_f count = 1, &count = 00007FF7172836D0

2.42

Function pointer square:

 use_f count = 2, &count = 00007FF7172836D0

1.4641

Function object Fp:

 use_f count = 3, &count = 00007FF7172836D0

6.05

Function object Fq:

 use_f count = 4, &count = 00007FF7172836D0

6.21

Lambda expression 1:

 use_f count = 5, &count = 00007FF7172836D0

1.4641

Lambda expression 2:

 use_f count = 6, &count = 00007FF7172836D0

1.815

 

D:\Prj\_C++Self\_33Wrapper_optimization\x64\Debug\_33Wrapper_optimization.exe (进程 1036)已退出,代码为 0。

要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。

按任意键关闭此窗口. . .

4 README

此为本人读C++ Primer总结的笔记,如有错误或知识缺口,请在评论区告知。如本文有在实践中帮到您,是本人的荣幸。

 

 

https://zhuanlan.zhihu.com/p/583655872

posted @   imxiangzi  阅读(81)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示