473,407 Members | 2,598 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,407 software developers and data experts.

Functors for complex tasks

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 1824
arnaudk
424 256MB
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 Expert 8TB
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
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
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 Expert 8TB
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 256MB
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
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
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 Expert 8TB
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
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....
41
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...
2
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...
1
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: ...
4
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()...
8
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...
4
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...
2
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...
4
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...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
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...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

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.