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 -
double Task1(string &filename) {
-
// Opening part of the reading loop
-
// Code to operate on one element at a time and perform task 1
-
// Closing part of the reading loop
-
}
-
-
double TaskSum(string &filename) {
-
-
double sum = 0;
-
-
// Opening part of the reading loop Identical!!!
-
// the value of the last read element is stored in el
-
-
sum += el;
-
-
// Closing part of the reading loop Identical !!!
-
-
return sum;
-
}
-
-
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? -
class tasks
-
{
-
public:
-
-
virtual void do(double el)=0;
-
virtual double result()=0;
-
};
-
-
-
-
class sumtask : public tasks
-
private:
-
double current;
-
-
public:
-
-
sumtask(): current(0) {} ;
-
void do(double el) { current += el; };
-
double result() { return current; };
-
-
};
-
-
-
-
void Task(string &filename, tasks &t) {
-
// Opening part of the reading loop Identical!!!
-
// the value of the last read element is stored in el
-
-
t.do(el);
-
-
// Closing part of the reading loop Identical !!!
-
return t.result();
-
}
-
-
-
int main(int argc, char* argv[]) {
-
string f = "file.bin";
-
sumtask t;
-
double result = Task(f, t);
-
}
-
-
I am using c++ compiled with gcc 4.0.1.
Thanks in advance,
Hernán
9 1824
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.
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: -
public:
-
void preprocess() = 0;
-
void process(double x) = 0;
-
double postprocess() = 0;
-
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
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
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
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
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.
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: -
void task(vector<double> &vIn, vector<double> &vOut, tasks &t) {
-
-
// Outer Loop.
-
// The following variables are updated in each iteration
-
// i is the iteration index
-
// start is the iterator of vIn that define the start of the subset
-
// end is the iterator of vIn that define the end of the subset
-
-
vOut[i] = t(start, end);
-
-
// End of the outer loop
-
-
}
-
-
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? -
class sometask {
-
double val;
-
vector <double> v;
-
public:
-
sometask (double i) :val(i) { }
-
-
operator double() const {
-
return val;
-
}
-
-
double operator()(iterator start, iterator end ) {
-
vector <double> tmp;
-
set_difference(start, end, v.begin(), v.end(), tmp);
-
v.swap(tmp);
-
return val+=accumulate(v.begin(), v.end());
-
}
-
};
-
Regards,
H
hi how are you?????
i hope to u all the best in your life....
please i want course in java (console application)
thanks
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)
Sign in to post your reply or Sign up for a free account.
Similar topics
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....
|
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...
|
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...
|
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:
...
|
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()...
|
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...
|
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...
|
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...
|
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...
|
by: Charles Arthur |
last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
|
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
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
|
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...
|
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...
|
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...
|
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...
|
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...
|
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...
| |