473,809 Members | 2,740 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Functors for complex tasks

4 New Member
Hello,

I am working on a program that must perform a certain task on numeric data stored in a file. The task is given by user input from a list of possible tasks.

The file has some particular format and I have already a loop that is able to read sequentially data from the file. The question is how to operate with the data inside the loop in an efficient way.

The straight forward way (which I did) is creating as many functions as tasks are defined, each function containing the same file reading loop but with a different part inside.

To give a simple example, let's say that I want to sum all the content of the file

Expand|Select|Wrap|Line Numbers
  1. double Task1(string &filename) {
  2. // Opening part of the reading loop
  3. // Code to operate on one element at a time and perform task 1
  4. // Closing part of the reading loop
  5. }
  6.  
  7. double TaskSum(string &filename) {
  8.  
  9. double sum = 0;
  10.  
  11. // Opening part of the reading loop Identical!!!
  12. // the value of the last read element is stored in el
  13.  
  14. sum += el;
  15.  
  16. // Closing part of the reading loop Identical !!!
  17.  
  18. return sum;
  19. }
  20.  
  21.  
And this for all tasks.

However, this is a nightmare to maintain and to expand. It will be also very annoying to perform the same tasks in other file type. That's why I would like to use function objects to do it. However, I am not sure how to do it in an appropriate way. The tasks that I need to perform most of the time need to keep some persistent information. Going back to my example before, Is the following code the most efficient way to do it using function objects? Will the performance be the same as the previous case?

Expand|Select|Wrap|Line Numbers
  1. class tasks
  2.    {
  3.    public:
  4.  
  5.       virtual void do(double el)=0;  
  6.       virtual double result()=0;
  7.    };
  8.  
  9.  
  10.  
  11. class sumtask : public tasks
  12.    private:
  13.     double current;
  14.  
  15.    public:
  16.  
  17.       sumtask(): current(0) {} ;
  18.       void do(double el) { current += el; };
  19.       double result() { return current; };
  20.  
  21.    };
  22.  
  23.  
  24.  
  25. void Task(string &filename, tasks &t) {
  26. // Opening part of the reading loop Identical!!!
  27. // the value of the last read element is stored in el
  28.  
  29. t.do(el);
  30.  
  31. // Closing part of the reading loop Identical !!!
  32. return t.result();
  33. }
  34.  
  35.  
  36. int main(int argc, char* argv[]) {
  37. string f = "file.bin";
  38. sumtask t;
  39. double result = Task(f, t);
  40. }
  41.  
  42.  
I am using c++ compiled with gcc 4.0.1.

Thanks in advance,

Hernán
Nov 8 '08 #1
9 1839
arnaudk
424 Contributor
I'm not sure what you mean by function objects since you don't use them in your example; function objects or functors overload operator(). It seems like you need to come up with a suitable abstraction for the file and the task so that the internals of the file abstraction can change depending on the file type independently to its interface as used by the task, which can then treat all file objects in the same way.
Nov 9 '08 #2
JosAH
11,448 Recognized Expert MVP
Remove the reading of the file part from your tasks and read up on the 'strategy'
pattern. Basically you want to do something with a sequence of numbers. Define
an abstract class Task that represents the number processing:

Expand|Select|Wrap|Line Numbers
  1. public:
  2.    void preprocess() = 0;
  3.    void process(double x) = 0;
  4.    double postprocess() = 0;
  5.  
All your 'concrete' tasks inherit from this abstract class and implement the
methods mentioned above.

Define a 'driver' class that does the file reading; the driver class is passed one
or more task class. While reading those numbers it activates the methods
defined in the task class.

Basically your driver class doesn't know what task it calls and the task(s) doesn't
know where these numbers come from but both do what they have to do. You
can call your driver class with different tasks without changing any code at all.
This is the strategy pattern in a nutshell.

kind regards,

Jos
Nov 9 '08 #3
hgrecco
4 New Member
I'm not sure what you mean by function objects since you don't use them in your example; function objects or functors overload operator(). It seems like you need to come up with a suitable abstraction for the file and the task so that the internals of the file abstraction can change depending on the file type independently to its interface as used by the task, which can then treat all file objects in the same way.
Thanks for the answer. This is exactly one of the problems. All examples that I have seen overloading operator() involve operations without memory, they do what they have to do in the current element and they do not remember anything of the past. Which is the efficient way to define a functor with state?

Thanks,

Hernan
Nov 9 '08 #4
hgrecco
4 New Member
Hi Jos,

Thanks for the reply. I tried your idea and is working fine. I wrote it using iterators so I can also use vectors or other STL containers.

As I pointed out in my other reply, I still would like to know how to implement efficient functors with state. Please do not close the thread.

Thanks,

Hernan
Nov 9 '08 #5
JosAH
11,448 Recognized Expert MVP
Thanks for the reply. I tried your idea and is working fine. I wrote it using iterators so I can also use vectors or other STL containers.

As I pointed out in my other reply, I still would like to know how to implement efficient functors with state. Please do not close the thread.
There's no reason at all to close this thread; it's a nice change compared to. all
the crap that is posted in here ;-)

A functor is just a class that overloads the operator() operator, so you're free to
do in that method whatever you want. I don't see the problem. Care to elaborate?

kind regards,

Jos
Nov 9 '08 #6
arnaudk
424 Contributor
Which is the efficient way to define a functor with state?
I don't see why you can't have a functor class with data members, then objects of that class will be function objects which retain a state. If you need to share a state across all function objects of a certain class, then you can use a static member. This being said, I don't see how function objects are really relevant to your specific problem; implementing the suggestions in post#3 should do it.
Nov 10 '08 #7
hgrecco
4 New Member
Thanks for all the comments and suggestions. My problem is not how to do a specific task, but how to do it in a maintainable and efficient (fast executing code) way.

While trying to understand what was bothering me, I found (again) something that I read sometime ago (and I forgot because I never used it) in Stroustrup faq

class Sum {
int val;
public:
Sum(int i) :val(i) { }
operator int() const { return val; } // extract value
int operator()(int i) { return val+=i; } // application
};

Note that a function object with an inline application operator inlines beautifully because there are no pointers involved that might confuse optimizers.
What I do not know is how to write function objects (or other classes) in a way that the mentioned optimization always take place. Of course I can profile (and indeed I do) but it would be nice to have some a priori guidelines.

Let me give another example. Let's say I need to populate a vector (vOut) with calculations that come from subsets of another one (vIn). How the subsets are defined are part of my outer loop and it is the same for all tasks. What to do with the subset changes from task to task.

So:
Expand|Select|Wrap|Line Numbers
  1. void task(vector<double> &vIn, vector<double> &vOut, tasks &t) {
  2.  
  3. // Outer Loop.
  4. // The following variables are updated in each iteration
  5. //  i is the iteration index
  6. //  start is the iterator of vIn that define the start of the subset 
  7. //  end is the iterator of vIn that define the end of the subset
  8.  
  9. vOut[i] = t(start, end);
  10.  
  11. // End of the outer loop
  12.  
  13. }
  14.  
  15.  
If t is an STL function like accumulate, the resulting binary will be the same as if I had written the code to do this operation directly inside the loop. How can I write function that keep this characteristic? For example, Will the following task also be inlined?

Expand|Select|Wrap|Line Numbers
  1. class sometask {
  2.     double val;
  3.     vector <double> v;
  4. public:
  5.     sometask (double i) :val(i) { }
  6.  
  7.     operator double() const {
  8.          return val;
  9.          }
  10.  
  11.     double operator()(iterator start, iterator end ) {        
  12.         vector <double> tmp;
  13.         set_difference(start, end, v.begin(), v.end(), tmp);
  14.         v.swap(tmp);
  15.         return val+=accumulate(v.begin(), v.end());
  16.      }
  17. };
  18.  
Regards,

H
Nov 11 '08 #8
safaaa
1 New Member
hi how are you?????
i hope to u all the best in your life....
please i want course in java (console application)
thanks
Nov 12 '08 #9
JosAH
11,448 Recognized Expert MVP
hi how are you?????
i hope to u all the best in your life....
please i want course in java (console application)
thanks
1) This is the C and C++ forum;
2) you're hijacking someone else's thread; that is rude.

kind regards,

Jos (moderator)
Nov 12 '08 #10

Sign in to post your reply or Sign up for a free account.

Similar topics

0
1742
by: red floyd | last post by:
Disclaimer: VS.NET 2003 (haven't checked any other compiler). I'm writing functors for my classes. Because the objects in my containers are large, I'm making my functors take const T& parameters. If I try std::bind2nd() with one of these classes, I get an error about a reference to a reference. What's the proper way to declare functors taking const T& parameters so that they play nicely with adapters? Would it be something like the...
41
3096
by: AngleWyrm | last post by:
I have created a new container class, called the hat. It provides random selection of user objects, both with and without replacement, with non-uniform probabilities. Uniform probabilities are a degenerate case, and can also be stored. Here's the web-page, with complete source, illustration, and example usage. Take a look-see, and post your critique! http://home.comcast.net/~anglewyrm/hat.html
2
1557
by: nsgi_2004 | last post by:
Hi, I have been learning about functors and at first everything was clear. Make a class and overload operator () so that an object of the functor can be thought of as a function. However, I have seen in Effective STL, Scott passes normal functions into places that expect functors. I'm not sure how this works, as I thought functors had to be classes.
1
1217
by: Matthias | last post by:
Hello, I basically want to implement a general resource manager which should have a caching and a loading policy so that I can exchange those. Here's some example code of how it should work: ResourceManager< SimpleCachingPolicy<Image, SimpleImageLoader> > imageMgr; ResourceManager< SimpleCachingPolicy<Sound, SimpleSoundLoader> > soundMgr; imageMgr.Load(filename, 1234);
4
2082
by: Fraser Ross | last post by:
Functors taking 1 argument for operator() should inherit from unary_function and those with 2 arguments should inherit from binary_function. If a functor has zero arguments for its operator() should it inherit from anything to make it adaptable? I've not heard of anything before which is surprising. If books don't talk about it then its an unanswered question to many people. Maybe its adaptable without inheriting anything, which would...
8
4537
by: michael.lesniak | last post by:
Hello, I'm learning C++ for a couple of days and play a bit with the algorithms provided in the STL. One thing I don't understand is the fact that classes inherited of functors have to be defined using structs. The code template<class type> struct Print : public unary_function<type, void> {
4
2242
by: tryptik | last post by:
Hello all, I have a question about iterators. I have a container of functors that operate on an std::string. The functors go something like this: class Functor { std::string operator()(const std::string& s) {/*manipulate string*/; return newString;} };
2
1755
by: Jon Slaughter | last post by:
I'm trying to mess with functors and the way I want it to work is that when I create a functor it will automatically add itself to an array. The attached code demonstrates what I mean. The problem is that its a bit unsatisfactory and I'd like to improve it. In the constructor of TClassA Functors<TClassA, std::string*Functor = new Functors<TClassA, std::string>(this, &TClassA::Display);
4
2753
by: Christopher | last post by:
I used to just use a plain old function pointer is a call to std::sort. My colleagues are telling me that I need to use a "functor". Ok, I google and see that a functor is a class with a public method, operator () that does the comparison. Fine, no problem. What they fail to tell me is, what is the advantage to wrapping some comparison function in a class and calling it operator()? I also read that "functors" are supposed to be a...
0
9721
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
10637
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
10379
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10115
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
9199
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
5550
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5687
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
3861
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
3014
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.