{"id":272,"date":"2017-05-12T11:54:24","date_gmt":"2017-05-12T11:54:24","guid":{"rendered":"http:\/\/imalogic.com\/blog\/?p=272"},"modified":"2017-05-14T10:06:15","modified_gmt":"2017-05-14T10:06:15","slug":"c-functor","status":"publish","type":"post","link":"https:\/\/imalogic.com\/blog\/2017\/05\/12\/c-functor\/","title":{"rendered":"C++ Functor"},"content":{"rendered":"<body><p>\u00a0<\/p>\n<p>A functor is pretty much just a class which defines the operator().<\/p>\n<p>That lets you create objects which \u201clook like\u201d a function:<\/p>\n<pre class=\"lang-cpp prettyprint prettyprinted\"><code><span class=\"com\">\/\/ this is a functor<\/span>\r\n<span class=\"kwd\">struct<\/span><span class=\"pln\"> add_x <\/span><span class=\"pun\">{<\/span><span class=\"pln\">\r\n  add_x<\/span><span class=\"pun\">(<\/span><span class=\"typ\">int<\/span><span class=\"pln\"> x<\/span><span class=\"pun\">)<\/span> <span class=\"pun\">:<\/span><span class=\"pln\"> x<\/span><span class=\"pun\">(<\/span><span class=\"pln\">x<\/span><span class=\"pun\">)<\/span> <span class=\"pun\">{}<\/span>\r\n  <span class=\"typ\">int<\/span> <span class=\"kwd\">operator<\/span><span class=\"pun\">()(<\/span><span class=\"typ\">int<\/span><span class=\"pln\"> y<\/span><span class=\"pun\">)<\/span> <span class=\"kwd\">const<\/span> <span class=\"pun\">{<\/span> <span class=\"kwd\">return<\/span><span class=\"pln\"> x <\/span><span class=\"pun\">+<\/span><span class=\"pln\"> y<\/span><span class=\"pun\">;<\/span> <span class=\"pun\">}<\/span>\r\n\r\n<span class=\"kwd\">private<\/span><span class=\"pun\">:<\/span>\r\n  <span class=\"typ\">int<\/span><span class=\"pln\"> x<\/span><span class=\"pun\">;<\/span>\r\n<span class=\"pun\">};<\/span>\r\n\r\n<span class=\"com\">\/\/ Now you can use it like this:<\/span><span class=\"pln\">\r\nadd_x add42<\/span><span class=\"pun\">(<\/span><span class=\"lit\">42<\/span><span class=\"pun\">);<\/span> <span class=\"com\">\/\/ create an instance of the functor class<\/span>\r\n<span class=\"typ\">int<\/span><span class=\"pln\"> i <\/span><span class=\"pun\">=<\/span><span class=\"pln\"> add42<\/span><span class=\"pun\">(<\/span><span class=\"lit\">8<\/span><span class=\"pun\">);<\/span> <span class=\"com\">\/\/ and \"call\" it<\/span><span class=\"pln\">\r\nassert<\/span><span class=\"pun\">(<\/span><span class=\"pln\">i <\/span><span class=\"pun\">==<\/span> <span class=\"lit\">50<\/span><span class=\"pun\">);<\/span> <span class=\"com\">\/\/ and it added 42 to its argument<\/span><span class=\"pln\">\r\n\r\nstd<\/span><span class=\"pun\">::<\/span><span class=\"typ\">vector<\/span><span class=\"str\">&lt;int&gt;<\/span><span class=\"pln\"> in<\/span><span class=\"pun\">;<\/span> <span class=\"com\">\/\/ assume this contains a bunch of values)<\/span><span class=\"pln\">\r\nstd<\/span><span class=\"pun\">::<\/span><span class=\"typ\">vector<\/span><span class=\"str\">&lt;int&gt;<\/span><span class=\"pln\"> out<\/span><span class=\"pun\">(<\/span><span class=\"pln\">in<\/span><span class=\"pun\">.<\/span><span class=\"pln\">size<\/span><span class=\"pun\">());<\/span>\r\n<span class=\"com\">\/\/ Pass a functor to std::transform, which calls the functor on every element <\/span>\r\n<span class=\"com\">\/\/ in the input sequence, and stores the result to the output sequence<\/span><span class=\"pln\">\r\nstd<\/span><span class=\"pun\">::<\/span><span class=\"pln\">transform<\/span><span class=\"pun\">(<\/span><span class=\"pln\">in<\/span><span class=\"pun\">.<\/span><span class=\"pln\">begin<\/span><span class=\"pun\">(),<\/span><span class=\"pln\"> in<\/span><span class=\"pun\">.<\/span><span class=\"pln\">end<\/span><span class=\"pun\">(),<\/span><span class=\"pln\"> out<\/span><span class=\"pun\">.<\/span><span class=\"pln\">begin<\/span><span class=\"pun\">(),<\/span><span class=\"pln\"> add_x<\/span><span class=\"pun\">(<\/span><span class=\"lit\">1<\/span><span class=\"pun\">));<\/span><span class=\"pln\"> \r\nassert<\/span><span class=\"pun\">(<\/span><span class=\"pln\">out<\/span><span class=\"pun\">[<\/span><span class=\"pln\">i<\/span><span class=\"pun\">]<\/span> <span class=\"pun\">==<\/span><span class=\"pln\"> in<\/span><span class=\"pun\">[<\/span><span class=\"pln\">i<\/span><span class=\"pun\">]<\/span> <span class=\"pun\">+<\/span> <span class=\"lit\">1<\/span><span class=\"pun\">);<\/span> <span class=\"com\">\/\/ for all i<\/span><\/code><\/pre>\n<p>There are a couple of nice things about functors. One is that unlike regular functions, they can contain state. The above example creates a function which adds 42 to whatever you give it. But that value 42 is not hardcoded, it was specified as a constructor argument when we created our functor instance. I could create another adder, which added 27, just by calling the constructor with a different value. This makes them nicely customizable.<\/p>\n<p>As the last lines show, you often pass functors as arguments to other functions such as std::transform or the other standard library algorithms. You could do the same with a regular function pointer except, as I said above, functors can be \u201ccustomized\u201d because they contain state, making them more flexible (If I wanted to use a function pointer, I\u2019d have to write a function which added exactly 1 to its argument. The functor is general, and adds whatever you initialized it with), and they are also potentially more efficient. In the above example, the compiler knows exactly which function <code>std::transform<\/code> should call. It should call <code>add_x::operator()<\/code>. That means it can inline that function call. And that makes it just as efficient as if I had manually called the function on each value of the vector.<\/p>\n<p>If I had passed a function pointer instead, the compiler couldn\u2019t immediately see which function it points to, so unless it performs some fairly complex global optimizations, it\u2019d have to dereference the pointer at runtime, and then make the call.<\/p>\n<p>\u00a0<\/p>\n<\/body>","protected":false},"excerpt":{"rendered":"<p>\u00a0 A functor is pretty much just a class which defines the operator(). That lets you create objects which \u201clook<\/p>\n","protected":false},"author":1,"featured_media":301,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[7],"tags":[24,26,57,64,27],"class_list":["post-272","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-coding","tag-c","tag-code","tag-coding","tag-functor","tag-programming"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/imalogic.com\/blog\/wp-content\/uploads\/2017\/05\/images.jpg?fit=266%2C190&ssl=1","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p8J21V-4o","jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/posts\/272","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/comments?post=272"}],"version-history":[{"count":1,"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/posts\/272\/revisions"}],"predecessor-version":[{"id":336,"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/posts\/272\/revisions\/336"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/media\/301"}],"wp:attachment":[{"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/media?parent=272"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/categories?post=272"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/tags?post=272"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}