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)

相关推荐

  • 腊肠炒饭,什么食物搭配蛋炒饭会好吃到爆

    技术腊肠炒饭,什么食物搭配蛋炒饭会好吃到爆来个高逼格的什锦芝士焗饭吧腊肠炒饭,简单地说就是蛋炒饭上铺一层芝士,然后微波炉一加热,丝丝香甜的芝士焗饭就做好了哦所需材料:米饭,香肠,白玉菇(可放可不放),土豆,玉米粒少许,马

    生活 2021年10月30日
  • 人有多少块肌肉,人最坚硬的肌肉是哪块啊`?

    技术人有多少块肌肉,人最坚硬的肌肉是哪块啊`?人体共约639块肌肉,我们生活中的一切动作,都是在神经系统的调控下,由肌肉的收缩和舒张带动骨人有多少块肌肉、关节运动而实现的。现在,摸摸你的身体,你觉得哪块肌肉最强壮?舌头、

    生活 2021年10月27日
  • 手打虾滑,现在比较有特色的火锅有哪些

    技术手打虾滑,现在比较有特色的火锅有哪些如今的火锅店是越来越多,品种也越来越多了,想吃火锅了,再也不单单是在铜锅涮肉和川味火锅中选择了,日本的寿喜锅,韩国的部队火锅,潮汕牛肉火锅,港式小火锅,梭边鱼火锅,贵州的酸汤鱼火锅

    生活 2021年10月30日
  • 衣服起球怎么快速去除,洗衣服时沾上许多毛毛怎么处理

    技术衣服起球怎么快速去除,洗衣服时沾上许多毛毛怎么处理洗衣服时沾上许多毛毛怎么处理?这个问题分两个方面来回答。第一衣服起球怎么快速去除,洗衣服时沾上许多毛毛怎么处理,最简单实用的,就是用透明胶带,把毛毛粘掉。还可以等衣服

    生活 2021年10月22日
  • microsoft.netframework有病毒吗(microsoftnetframework有害处吗)

    技术Microsoft .NET Framework漏洞是怎么样的这篇文章给大家介绍Microsoft .NET Framework漏洞是怎么样的,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。0x0

    攻略 2021年12月21日
  • 描写花草树木的成语,描写花草树木的成语有什么写三个

    技术描写花草树木的成语,描写花草树木的成语有什么写三个花草树木的成语描写花草树木的成语: 繁花似锦、绿草如茵、郁郁葱葱、古树参天、万木争荣、百花齐放 花团锦簇、万紫千红、桃红柳绿草木皆兵 寸草不生 百花齐放 百花争艳 遍

    生活 2021年10月24日