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)

相关推荐

  • 您考虑的任何香港云服务器都应该提供的5个功能

    技术您考虑的任何香港云服务器都应该提供的5个功能无论您的独特需求是什么,每个网站所有者都应该在租用云服务器的时候关注五件事。1.可靠的性能 您想自信地知道,只要有人尝试导航到您的网站,他们就会看到您设计的网站。否则,你付

    礼包 2021年11月9日
  • JAVA中Throw和throws的区别有哪些

    技术JAVA中Throw和throws的区别有哪些本篇内容主要讲解“JAVA中Throw和throws的区别有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JAVA中Th

    攻略 2021年11月20日
  • 红领巾心向党征文,求一个红领巾心向党的童谣

    技术红领巾心向党征文,求一个红领巾心向党的童谣红领巾心向党 童谣 自己写的,不得抄袭,发到我邮箱 不发到邮箱不给分 :我爱红领巾 少先队员真光荣, 庄严宣誓记心中红领巾心向党征文。 爱国爱校爱班级, 认真学习要用功。 文

    生活 2021年10月29日
  • 如何理解SAP HANA Hint

    技术如何理解SAP HANA Hint本篇文章为大家展示了如何理解SAP HANA Hint,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。什么是SAP HANA HintHANA

    攻略 2021年11月23日
  • 三个向造句,用“向”“向”“向”三个词造句

    技术三个向造句,用“向”“向”“向”三个词造句在大会上我们向英雄致敬,向英雄献花,还宣誓要向英雄学习三个向造句。花儿向太阳微笑,向风儿点头,向蜜蜂问好。我向小猫学喵喵叫,向袋鼠学跳跃,向猴子学爬树。向前、向前,向前,我们

    生活 2021年10月21日
  • 如何通过串口控制树莓派

    技术如何通过串口控制树莓派这篇文章给大家分享的是有关如何通过串口控制树莓派的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。通过串口控制树莓派需求在没有网络,没用键盘,没有显示器的情况下,控制树莓

    攻略 2021年11月20日