473,383 Members | 1,872 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,383 software developers and data experts.

Problem using mem_fun.

I've got a function that I use a lot when making utility programs
that need to do the same thing to every directory in a tree.
Its prototype is:

unsigned long int CursDirs (void Func(void));

This just applies the fuction Func to every subdirectory of the
current directory. It works fine when I pass it pointers to regular
void-void functions.

But last night I had a situation where it would be very handy to pass
it a pointer to a member function of a class. This is in a program
that counts lines of text in all *.c, *.cpp, and *.h files in a
directory tree, starting at current directory and recursively descending.
(Basically, "line count of this project".) In this program, I have
this class:

class SourceTree
{
public:
SourceTree(void) : Lines(0UL) {}
void CountLines(void);
void PrintLines(void);
private:
void CountLinesInFile (const std::string& FileName);
void CountLinesInCurDir (void);
unsigned long int Lines;
};

I tried to pass &SourceTree::CountLinesInCurDir to CursDirs:

SourceTree::CountLines(void)
{
CursDirs(&SourceTree::CountLinesInCurDir);
return;
}

but OOPS, that's not allowed!

So I tried to use mem_fun from <functional> like this:

SourceTree::CountLines(void)
{
CursDirs(mem_fun(&SourceTree::CountLinesInCurDir)) ;
return;
}

But that doesn't work either. I get an error message saying
"cannot convert std::mem_fun_t<void, SourceTree> to void(*)()"

What am I doing wrong here? Is there a way to get mem_fun to
work in this application, or is this too far removed from it's
original intended purpose (ie, std. algorithms)?

(In the mean time, I had to copy&paste the entire body of CursDirs
into CountLines. This works, but is very messy. It'd sure be nice
to be able to do it in one line instead.)

--
Cheers,
Robbie Hatley
Tustin, CA, USA
email: lonewolfintj at pacbell dot net
web: home dot pacbell dot net slant earnur slant

Jul 22 '05 #1
2 1975

"Robbie Hatley" <lonewolfintj at pacbell dot net> wrote in message
news:41**********@127.0.0.1...
I've got a function that I use a lot when making utility programs
that need to do the same thing to every directory in a tree.
Its prototype is:

unsigned long int CursDirs (void Func(void));

This just applies the fuction Func to every subdirectory of the
current directory. It works fine when I pass it pointers to regular
void-void functions.

But last night I had a situation where it would be very handy to pass
it a pointer to a member function of a class. This is in a program
that counts lines of text in all *.c, *.cpp, and *.h files in a
directory tree, starting at current directory and recursively descending.
(Basically, "line count of this project".) In this program, I have
this class:

class SourceTree
{
public:
SourceTree(void) : Lines(0UL) {}
void CountLines(void);
void PrintLines(void);
private:
void CountLinesInFile (const std::string& FileName);
void CountLinesInCurDir (void);
unsigned long int Lines;
};

I tried to pass &SourceTree::CountLinesInCurDir to CursDirs:

SourceTree::CountLines(void)
{
CursDirs(&SourceTree::CountLinesInCurDir);
return;
}

but OOPS, that's not allowed!

So I tried to use mem_fun from <functional> like this:

SourceTree::CountLines(void)
{
CursDirs(mem_fun(&SourceTree::CountLinesInCurDir)) ;
return;
}

But that doesn't work either. I get an error message saying
"cannot convert std::mem_fun_t<void, SourceTree> to void(*)()"

What am I doing wrong here? Is there a way to get mem_fun to
work in this application, or is this too far removed from it's
original intended purpose (ie, std. algorithms)?


The return from mem_fun is a functor, not a function pointer. In any case
mem_fun doesn't help you in this particular case because you have no way to
pass the class itself into CurDirs.

You need a refresher course in functors.

The first thing you should do is rewrite CursDirs as a template so that it
can use either a function pointer or a functor.

template <class F>
unsigned long int CursDirs (F func)
{
...
func();
...
}

Then you should write your own functor that can call the member function you
want

struct LineCounter
{
LineCounter(SourceTree* tree) : _tree(tree) {}
void operator()() const
{
tree->CountLinesInCurDir();
}
private:
SourceTree* _tree;
};

Finally you use it like this

SourceTree::CountLines(void)
{
CursDirs(LineCounter(this));
}

This is untested code, but hopefully you get the idea.

john
Jul 22 '05 #2
Greetings, John Harrison. You wrote:
"Robbie Hatley" <lonewolfintj at pacbell dot net> wrote in message
news:41**********@127.0.0.1...
I've got a function that I use a lot when making utility programs
that need to do the same thing to every directory in a tree.
Its prototype is:

unsigned long int CursDirs (void Func(void));

This just applies the fuction Func to every subdirectory of the
current directory. It works fine when I pass it pointers to regular
void-void functions.

But last night I had a situation where it would be very handy to pass
it a pointer to a member function of a class. This is in a program
that counts lines of text in all *.c, *.cpp, and *.h files in a
directory tree, starting at current directory and recursively descending.
(Basically, "line count of this project".) In this program, I have
this class:

class SourceTree
{
public:
SourceTree(void) : Lines(0UL) {}
void CountLines(void);
void PrintLines(void);
private:
void CountLinesInFile (const std::string& FileName);
void CountLinesInCurDir (void);
unsigned long int Lines;
};

I tried to pass &SourceTree::CountLinesInCurDir to CursDirs:

SourceTree::CountLines(void)
{
CursDirs(&SourceTree::CountLinesInCurDir);
return;
}

but OOPS, that's not allowed!

So I tried to use mem_fun from <functional> like this:

SourceTree::CountLines(void)
{
CursDirs(mem_fun(&SourceTree::CountLinesInCurDir)) ;
return;
}

But that doesn't work either. I get an error message saying
"cannot convert std::mem_fun_t<void, SourceTree> to void(*)()"

What am I doing wrong here? Is there a way to get mem_fun to
work in this application, or is this too far removed from it's
original intended purpose (ie, std. algorithms)?

The return from mem_fun is a functor, not a function pointer. In any case
mem_fun doesn't help you in this particular case because you have no way to
pass the class itself into CurDirs.

Aye, I can see now, that is just the problem: CursDirs does not
have any way of calling CountLinesInCurDir through the "this"
pointer of the one and only SourceTree instance in my program.

You need a refresher course in functors.

The first thing you should do is rewrite CursDirs as a template so that it
can use either a function pointer or a functor.

template <class F>
unsigned long int CursDirs (F func)
{
...
func();
...
}

I did that, and it works fine. I can see how the template
parameter F makes func more "generic" so that CursDirs
will now work with either a function or a functor.

Thanks for the tip!

Then you should write your own functor that can call the member function you
want

struct LineCounter
{
LineCounter(SourceTree* tree) : _tree(tree) {}
void operator()() const
{
tree->CountLinesInCurDir();
}
private:
SourceTree* _tree;
};

Finally you use it like this

SourceTree::CountLines(void)
{
CursDirs(LineCounter(this));
}

This is untested code, but hopefully you get the idea.

john

Yes, that works very well! I actually put two such functors
in my program based around your "LineCounter", one to pass
a SourceTree member function to three "for_each" statements,
and the other to pass a SourceTree member function to CursDirs.

Perhaps I should try to templatize those as generic "Glue Functors".
Could be very useful for allowing functions and algorithms
to call member functions of types other than the argument type.

Thanks again for the help!
--
Cheers,
Robbie Hatley
Tustin, CA, USA
email: lonewolfintj at pacbell dot net
web: home dot pacbell dot net slant earnur slant
Jul 22 '05 #3

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
by: Mr X | last post by:
Can anyone tell how to fix the compile error for the program below? #include "iostream.h" #include <vector> #include <algorithm> #include <functional> #include <list> using namespace std;
11
by: franklini | last post by:
hello people, just wanted to say thanks again for the help in the past. i have a new problem which am wondering if any body can help me with. i have written this abtract class shape and its...
4
by: ShaneG | last post by:
We have ptr_fun to handle functions, mem_fun to handle member functions that will be called through a pointer, and mem_fun_ref to handle member functions that will be called through a reference. ...
2
by: IndyStef | last post by:
I am trying to use boost's bind on a member function, on the VC8 compiler. After using several different attempts, I could not get it to work. Does anybody know what is wrong with the code below?...
6
by: Belebele | last post by:
Suppose I want to use some object's member function as the action passed to a for_each call: class A { ... public: void foo(int ); }; A a;
15
by: fungus | last post by:
I'm moving some code from VC++ 6 to VC++ 2005 and I've run into a nasty problem because iterators are no longer pointers. In the program I'm moving, there's a std::vector of items hidden inside...
4
by: joseph cook | last post by:
I am getting a compile error on any compiler I try, so I know I have an error here. Can anyone see it? //includes class Foo { public: Foo(int a){m_hi = a;} int hi(){return m_hi;}
1
by: subramanian100in | last post by:
Suppose I have class WordAndLineNumbers { public: void print( ); // other member functions private: // data members
2
by: church7 | last post by:
Hello, I wrote the following class: In this case, the error message was
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 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 former...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
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: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
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
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
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...

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.