C++ std::function的简单实现以及函数指针

技术C++ std::function的简单实现以及函数指针 C++ std::function的简单实现以及函数指针敢在简历里写“精通C++”或“熟练掌握C++”的人,都已经被面试官问死了……
今天闲

std:函数和函数指针的简单实现。

凡是敢在简历上写“精通C”或“精通C”的人,都被面试官问死了.

今天没事干,想着怎么实现std:function功能,反正呆着也没意思。

首先使用它:

1 my functionint(const STD :3360 string)fc=test _ func;

2 int len=fc(' as dasd ');

实现后,暂时的目标是让这两句话成功运行。其中myfunction是实现类似std:函数的类名;Test_func是一个函数指针,其参数类型为const string,返回值为intFc是一个变量名,我想用它来进行函数调用。

显然,myfunction类是一个只有一个模板参数的模板类,所以您可以先这样做:

1模板类型名T

2类函数

3 {

4 };

下一步是什么.

看看第二行代码:

int len=fc(' as dasd ');

这句话包含了很多信息:

1.因为fc是myfunction类的实例化对象,它执行类似obj(xxx)的操作,所以需要重载operator()的运算符。

2.根据1,在运算符()的重载中,类型字符串的参数是必需的,即test_func函数的参数。换句话说,你需要知道myfunction参数的类型,然后才能通用。

3.同样,您需要知道test_func函数返回值的类型;

综上所述,接下来的——。

1 templatetypename TRet,typename TArg1

2级myfunctionTRet(TArg1)

3 {

4公众号:

5 myfunction() {}

6 ~myfunction() {}

8 public:

9 TRet运算符()(TArg1 arg1)

10 {

11 }

12

13 TRet(*)(TArg1)运算符=(TRet(*)(TArg1) fc)

14 {

15 }

16

17 };

类myfunctionTRet(TArg1)使用模板专门化。这种写法不常见,尤其是里面的模板参数。

当然,上面代码中的函数指针不能这样写,比如形式参数fc需要更改,任何人都可以这样写。

1 templatetypename TRet,typename TArg1

2级myfunctionTRet(TArg1)

3 {

4公众号:

5 myfunction() {}

6 ~myfunction() {}

8 public:

9 TRet运算符()(TArg1 arg1)

10 {

11 }

12

13 TRet(*)(TArg1)运算符=(TRet(*fc)(TArg1))

14 {

15 }

16

17 };

当我们填入真正可用的指针和两个运算符重载函数时,代码就差不多完成了。

1 templatetypename TRet,typename TArg1

2级myfunctionTRet(TArg1)

3 {

4公众号:

5 myfunction() : _fc(NULL) {}

6 ~myfunction() {}

8 myfunction(TRet(*fc)(TArg1))

9 : _fc(fc)

10 {

11 }

12

13 public:

14 TRet运算符()(TArg1 arg1)

15 {

16 if (_fc==NULL)

17 {

18掷(STD : logic _ error(' The _ fc为nullptr!'));

19返回TRet();

20 }

21

22 return _ fc(arg 1);

23 }

24

25 TRet(*)(TArg1)运算符=(TRet(*fc)(TArg1))

26 {

27 _ fc=fc

28 return _ fc

29 }

30

31列兵:

32 TRet(* _ fc)(targ 1);

33 };

正在我高兴之余,我试着编译了一下……未通过!错在了第25行 :TRet(*)(TArg1) operator=(TRet(*fc)(TArg1))。也就是说,返回函数指针还不能这样写。

于是我转变了一下写法,把返回值类型typedef一下:

1 typedef TRet(*TFunc)(TArg1);
2 TFunc operator=(TRet(*fc)(TArg1))
3 { 
4     _fc = fc; 
5     return _fc; 
6 }

这样就可以了。

但是我从小就头铁,我就想知道,如果不用typedef该怎么办

试了好久都没成功,直到我看见了这个:

TRet(*fc)(TArg1)

也就是说,函数指针的定义法就不能按照普通的 type name; 的形式,应当是:

type_ret(*name)(type_arg)

这样的。所以,我把operator=函数改成了这样:

TRet(*operator=(TRet(*fc)(TArg1)))(TArg1) 

实际上,就是把operator=(TRet(*fc)(TArg1))这个没有返回值的函数体扔在了前面的星号后。

不就是递归吗我也会。

至此,整个类也就完成了,如下:

#include iostream
#include string
int test_func(const std::string a) { return a.size(); }
templatetypename T 
class myfunction 
{
};
templatetypename TRet, typename TArg1
class myfunctionTRet(TArg1)
{
public:
    myfunction() : _fc(NULL) {}
    ~myfunction() {}
    myfunction(TRet(*fc)(TArg1))
        : _fc(fc)
    {
    }
public:
    TRet operator()(TArg1 arg1)
    {
        if (_fc == NULL)
        {
            throw(std::logic_error("The _fc is nullptr!"));
            return TRet();
        }
        return _fc(arg1);
    }
    TRet(*operator=(TRet(*fc)(TArg1)))(TArg1) 
    { 
        _fc = fc; 
        return _fc; 
    }
private:
    TRet(*_fc)(TArg1);
};
int main()
{
    int (*fc)(const std::string) = test_func;
    size_t len = fc("asd");
    myfunctionint(const std::string) fc2 = test_func;
    int len2 = fc2("asdasd");
    std::cout  len2  std::endl;
    return 0;
}

因为不使用c++11的语法,也就是不能使用可变参数模板,此类只能用于一个参数的函数。如果两个的该怎么办

那就再特化一遍:

 1 templatetypename TRet, typename TArg1, typename TArg2
 2 class myfunctionTRet(TArg1, TArg2)
 3 {
 4 public:
 5     myfunction() : _fc(NULL) {}
 6     ~myfunction() {}
 7 
 8     myfunction(TRet(*fc)(TArg1, TArg2))
 9         : _fc(fc)
10     {
11     }
12 
13 public:
14     TRet operator()(TArg1 arg1, TArg2 arg2)
15     {
16         if (_fc == NULL)
17         {
18             throw(std::logic_error("The _fc is nullptr!"));
19             return TRet();
20         }
21 
22         return _fc(arg1, arg2);
23     }
24 
25     TRet(*operator=(TRet(*fc)(TArg1, TArg2)))(TArg1, TArg2) 
26     { 
27         _fc = fc; 
28         return _fc; 
29     }
30 
31 private:
32     TRet(*_fc)(TArg1, TArg2);
33 };

为了兼容更多参数的函数,你可能要特化好多遍这个代码。当没有语法支持时,好多人都这么干。

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/51641.html

(0)

相关推荐

  • 快速建站选择台湾云服务器有什么好处

    技术快速建站选择台湾云服务器有什么好处很多新站长对于租用服务器应该选择什么样的海外服务器还是比较困惑的,尤其是目前市面上的除了物理服务器、云服务器、VPS的平台区别之外,对于哪个地区的机房更合适也有不了解的地方,就最近各

    礼包 2021年10月30日
  • 奔怎么组词,“奔”字的多音字怎么组词

    技术奔怎么组词,“奔”字的多音字怎么组词奔拼音:【bēn/bèn】其中奔【bèn】的意思和相关组词如下:奔【 bèn】1、直向目的地走去:投奔。直奔工地。他顺着小道直奔那山头。奔向小康。投奔【tóubèn】指前往依靠别人

    生活 2021年10月21日
  • 怎么实现Hadoop集群搭建

    技术怎么实现Hadoop集群搭建怎么实现Hadoop集群搭建,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。阅读编译文档 准备一个hadoop源码包,我选择的

    攻略 2021年11月16日
  • k8s搭建手札-kubeadm

    技术k8s搭建手札-kubeadm k8s搭建手札-kubeadm目标:1个master 2个node
    宿主机:3个centos7 parallel 虚拟机
    1. 关闭防火墙、关闭iptables规则、

    礼包 2021年11月15日
  • 怎么理解TiDB兼容MySQL参数优化

    技术怎么理解TiDB兼容MySQL参数优化本篇内容介绍了“怎么理解TiDB兼容MySQL参数优化”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔

    攻略 2021年11月8日
  • 竹字头一个见,竹字头下面一个即念什么

    技术竹字头一个见,竹字头下面一个即念什么竹字头下面一个均念筠竹字头一个见,读音为yún jūn。 含义如下: 筠Jūn〈名〉 1 唐羁縻州,其地即今四川省南部的筠连县。 2 另见 yún。 筠yún〈名〉 (1)形声。从

    生活 2021年10月26日