In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)05/31 Report--
Most people do not understand the knowledge points of this article "how to use std::mem_fn in Category 11", so the editor summarizes the following contents, detailed contents, clear steps, and has a certain reference value. I hope you can get something after reading this article. Let's take a look at this "how to use std::mem_fn in Craft 11" article.
1. Source code preparation
This article is based on the analysis of the source code of gcc-4.9.0, std::mem_fn is added to the standard, so the lower version of gcc source code is not std::mem_fn, it is recommended to choose 4.9.0 or newer version to learn, different versions of gcc source code should be different, but the principle and design ideas are the same.
2. Use a simple example to understand the role of std::mem_fn.
Algorithm is a very important part of C++ standard library. C++ separates the data structure from the algorithm through the way of algorithm + container, which can give users maximum flexibility when writing code. Suppose we have the following categories:
Class Age {public: Age (int v): m_age (v) {} bool compare (const Age& t) const {return m_age
< t.m_age; } int m_age;}; 我们可以非常方便地使用vector来保存Age对象,如下: std::vector ages{1, 7, 19, 27, 39, 16, 13, 18}; 然后非常方便的利用排序算法进行排序 std::sort(ages.begin(), ages.end(), compare); 代码中的compare是额外定义的一个比较函数,通过这个函数来选择比较的对象并决定比较的结果 bool compare(const Age& t1, const Age& t2){ return t1.compare(t2);} 严格来讲,算法中要求的并不是函数,而是一个可调用对象。C++中的可调用对象包括函数、函数对象、Lambda表达式、参数绑定等等,它们都可以作为算法的传入参数,但是如果我们按如下来传入参数的话,则会在编译过程中出现错误 std::sort(ages.begin(), ages.end(), &Age::compare); 因为&Age::compare是类成员函数,并非一个可调用对象,如果我们要将它作为比较的参数传递进去的话,就得用std::mem_fn修饰它,如下所示 std::sort(ages.begin(), ages.end(), std::mem_fn(&Age::compare)); 从上面的例子可以看到,std::mem_fn的作用就是将类的成员函数转换为一个可调用对象,那么问题来了,std::mem_fn是如何实现这种功能的呢?下面让我们通过分析源码,来揭开std::mem_fn的神秘面纱。 3、std::mem_fn源码解析 3.1、std::mem_fn解析 std::mem_fn位于libstdc++-v3\include\std\functional中 templateinline _Mem_fn mem_fn(_Tp _Class::* __pm) noexcept{ return _Mem_fn(__pm);} 从代码中可知std::mem_fn是一个模板函数,传入参数为指向_Class类里面的某个成员函数的指针,其返回值为_Tp,而该模板函数返回的值为_Mem_fn,接下来看一下_Mem_fn的实现 3.2、std::_Mem_fn解析 std::_Mem_fn位于libstdc++-v3\include\std\functional中 templateclass _Mem_fn : public _Maybe_unary_or_binary_function{ typedef _Res (_Class::*_Functor)(_ArgTypes...); template _Res _M_call(_Tp&& __object, const volatile _Class *, _Args&&... __args) const { return (std::forward(__object).*__pmf)(std::forward(__args)...); } template _Res _M_call(_Tp&& __ptr, const volatile void *, _Args&&... __args) const { return ((*__ptr).*__pmf)(std::forward(__args)...); } template using _RequireValidArgs = _Require; template using _RequireValidArgs2 = _Require; template using _RequireValidArgs3 = _Require;public: typedef _Res result_type; explicit _Mem_fn(_Functor __pmf) : __pmf(__pmf) {} template _Res operator()(_Class& __object, _Args&&... __args) const { return (__object.*__pmf)(std::forward(__args)...); } template _Res operator()(_Class&& __object, _Args&&... __args) const { return (std::move(__object).*__pmf)(std::forward(__args)...); } template _Res operator()(_Class* __object, _Args&&... __args) const { return (__object->* _ _ pmf) (std::forward (_ _ args)...);} template _ Res operator () (_ Tp&& _ object, _ Args&&... _ args) const {return _ M_call (std::forward (_ _ object), & _ _ object, std::forward (_ _ args).) } template _ Res operator () (reference_wrapper _ _ ref, _ Args&&... _ args) const {return operator () (_ _ ref.get (), std::forward (_ _ args)...);} private: _ Functor _ _ pmf;}
The following information can be seen from the source code:
This class inherits from _ Maybe_unary_or_binary_function. Since _ Maybe_unary_or_binary_function is not much related to the content analyzed in this article, you can query its usage on Baidu, so I won't introduce it here.
There is a member _ _ pmf in the class, whose type is a pointer to the class member function passed in mem_fn in the previous section, initialized by the constructor
Next, let's focus on the six overloaded () operator functions in the class. The operations in them are more or less the same. Basically, the _ _ pmf member functions are called through the objects (in various forms) of the class corresponding to _ _ pmf:
The first function _ Res operator () (_ Class& _ _ object, _ Args&&... _ _ args): you can see that it requires one more incoming parameter, namely _ _ object, than the original class member function, and the type is a reference to a class object. From the implementation of the function, you can see that the principle is to directly call the previous class member function through this class object (calling without this class object is not valid, because the class member function cannot be called directly. This is also the meaning of std::mem_fn)
The second function, _ Res operator () (_ Class&& _ _ object, _ Args&&... _ _ args): you can see that the first parameter passed in to this method is a right-value reference object, and the implementation in it is just to transfer the object through std::move. The other processing is exactly the same as before.
The third function, _ Res operator () (_ Class* _ _ object, _ Args&&... _ _ args): you can see that this method passes in an object pointer, and the other processing is exactly the same as before
The fifth function _ Res operator () (reference_wrapper _ _ ref, _ Args&&... _ _ args): you can see that this method has passed a reference wrapped by std::reference_wrapper, and the process is basically the same as the previous one, which is relatively simple, so we won't make any more analysis here. (for std::reference_wrapper, you can take a look at this article, "std::ref and std::cref source code parsing of Category 11", in which std::reference_wrapper is introduced in detail through source code analysis, so I won't repeat it here.)
The fourth function _ Res operator () (_ Tp&& _ _ object, _ Args&&... _ _ args): this is a bit more complicated. This function is used to handle a situation where the incoming parameter is a smart pointer or a derived class object. You can see that the _ M_call method is called in the function. The second parameter seems to be optional, but it is actually used to distinguish whether the incoming parameter type is a smart pointer or a derived class object for _ M_call.
The _ M_call implementation is as follows. As you can see, the first overload deals with derived class objects, and the second overload deals with smart pointers. The code is relatively simple, so there is no more analysis here. You can read it for yourself and understand it.
Template_Res _ M_call (_ Tp&& _ _ object, const volatile _ Class *, _ Args&&... _ args) const {return (std::forward (_ _ object). * _ _ pmf) (std::forward (_ _ args).) } template_Res _ M_call (_ Tp&& _ ptr, const volatile void *, _ Args&&... _ args) const {return ((* _ ptr). * _ pmf) (std::forward (_ _ args)...);} 3.3.3.Use std::_Mem_fn correctly in the code
The sample code is as follows. From a large section of analysis above, we can see that the ages [2] we have been analyzing is the incoming object used to call the class member function, and ages [3] is the normal input parameter needed by bool Age::compare (const Age& t), that is, the value in the above variable parameter. At this point, the analysis of the std::mem_fn source code is complete.
# include # include class Age {public: Age (int v): m_age (v) {} bool compare (const Age& t) const {return m_age < t.mage;} int mage;}; bool compare (const Age& T1, const Age& T2) {return t1.compare (T2) } int main (int argc, char* argv []) {std::vector ages {1,7,19,27,39,16,13,18}; bool ret = std::mem_fn (& Age::compare) (ages [2], ages [3]); / / std::sort (ages.begin (), ages.end (), std::mem_fn (& Age::compare)); return 0 } the above is about the content of this article on "how to use std::mem_fn in Craft 11". I believe we all have a certain understanding. I hope the content shared by the editor will be helpful to you. If you want to know more about the relevant knowledge, please follow the industry information channel.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.