C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Using local classes as functors: my first solution

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Guest






PostPosted: Thu Feb 09, 2006 4:06 pm    Post subject: Using local classes as functors: my first solution Reply with quote



Hi everyone,

I've been trying to find elegant ways to use local classes as functors
and pass them to the STL algorithms. Here is my first solution. I would
appreciate any critique or thoughts on weaknesses on my approach:

------------------------------------------------
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>

using namespace std;

template<class T>
class Functor {
public:
virtual bool operator()(T t1, T t2){return true;};
};

int main() {
vector<int> iv;
iv.push_back(1); iv.push_back(2); iv.push_back(3); iv.push_back(4);

struct Local_functor : public Functor<int> {
bool operator()(int i1, int i2) {return i1 > i2;}
} f;

sort(iv.begin(), iv.end(), dynamic_cast<Functor<int> &>(f));
copy(iv.begin(), iv.end(), ostream_iterator<int>(cout, "\n"));

return 0;
}
------------------------------------------------

/Ali


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Maxim Yegorushkin
Guest





PostPosted: Thu Feb 09, 2006 6:06 pm    Post subject: Re: Using local classes as functors: my first solution Reply with quote



ali_tof...@hotmail.com wrote:
Quote:
Hi everyone,

I've been trying to find elegant ways to use local classes as functors
and pass them to the STL algorithms. Here is my first solution. I would
appreciate any critique or thoughts on weaknesses on my approach:

------------------------------------------------
#include <iostream
#include <vector
#include <algorithm
#include <iterator

using namespace std;

template<class T
class Functor {
public:
virtual bool operator()(T t1, T t2){return true;};
};

int main() {

[]

Quote:
struct Local_functor : public Functor<int> {
bool operator()(int i1, int i2) {return i1 > i2;}
} f;

sort(iv.begin(), iv.end(), dynamic_cast<Functor<int> &>(f));

[]

Quote:
}

This won't work right because of slicing. Standard algorithms take a
functor by value rather than by reference. If you made
Functor::operator() pure virtual your compiler would have complained
about the inability to create a copy of a pure virtual Functor class.

If you can live with a virtual call to operator(), which may well
prohibit inlining the call, you can make your idea work like this:

#include <functional>
#include <algorithm>

template<class T1, class R>
struct unary_local_function
{
virtual R operator()(T1) = 0;
};

template<class T1, class R>
struct unary_local_function_ref : std::unary_function<T1, R>
{
unary_local_function<T1, R>* f;
unary_local_function_ref(unary_local_function<T1, R>* f) : f(f) {}
R operator()(T1 t) { return f->operator()(t); }
};

template<class T1, class R>
unary_local_function_ref<T1, R> make_ref(unary_local_function<T1, R>&
f)
{
return unary_local_function_ref<T1, R>(&f);
}

int main(int ac, char** av)
{
struct functor : unary_local_function<int, int>
{
int operator()(int i) { return i + 1; }
} f;

int* p = 0;
std::for_each(p, p, make_ref(f));
}


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Pete Becker
Guest





PostPosted: Thu Feb 09, 2006 6:06 pm    Post subject: Re: Using local classes as functors: my first solution Reply with quote



ali_tofigh (AT) hotmail (DOT) com wrote:

Quote:

sort(iv.begin(), iv.end(), dynamic_cast<Functor<int> &>(f));

STL algorithms take their arguments by value. Casting your object to a
reference doesn't change that. The code ends up slicing the object. Try
it with a derived type that holds some data that is used by operator().

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Franz
Guest





PostPosted: Fri Feb 10, 2006 2:06 am    Post subject: Re: Using local classes as functors: my first solution Reply with quote

Quote:

I've been trying to find elegant ways to use local classes as functors
and pass them to the STL algorithms. Here is my first solution. I would
appreciate any critique or thoughts on weaknesses on my approach:


Nice.

Quote:
struct Local_functor : public Functor<int> {
bool operator()(int i1, int i2) {return i1 > i2;}
} f;

sort(iv.begin(), iv.end(), dynamic_cast<Functor<int> &>(f));

Why aren't you using a static_cast?

sort(iv.begin(), iv.end(), static_cast<Functor<int> &>(f));

I think the dynamic_cast has runtime overhead while the static_cast is
done at compile time and works too.

- Franz


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
ALiX
Guest





PostPosted: Fri Feb 10, 2006 3:06 am    Post subject: Re: Using local classes as functors: my first solution Reply with quote

Quote:
This won't work right because of slicing. Standard algorithms take a
functor by value rather than by reference.

Does this mean that a reference type cannot be a template argument? I
didn't think further of it after I compiled the code using gcc. It
worked fine. It seems a little strange that the virtual call would
actually work if the object is sliced...

And thanks for your code suggestion.

/ALiX


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Michael Tiomkin
Guest





PostPosted: Fri Feb 10, 2006 3:06 am    Post subject: Re: Using local classes as functors: my first solution Reply with quote

ali_tofigh (AT) hotmail (DOT) com wrote:
Quote:
Hi everyone,

I've been trying to find elegant ways to use local classes as functors
and pass them to the STL algorithms. Here is my first solution. I would
appreciate any critique or thoughts on weaknesses on my approach:

------------------------------------------------
#include <iostream
#include <vector
#include <algorithm
#include <iterator

using namespace std;

template<class T
class Functor {
public:
virtual bool operator()(T t1, T t2){return true;};

I think you don't need a virtual method in this case

Quote:
};

int main() {
vector<int> iv;
iv.push_back(1); iv.push_back(2); iv.push_back(3); iv.push_back(4);

struct Local_functor : public Functor<int> {
bool operator()(int i1, int i2) {return i1 > i2;}
} f;

Unfortunately, your comparison functor doesn't accept as arguments
std::vector<int>iterator or std::vector<int>const_iterator

Quote:

sort(iv.begin(), iv.end(), dynamic_cast<Functor<int> &>(f));
copy(iv.begin(), iv.end(), ostream_iterator<int>(cout, "\n"));

return 0;
}

The standard solution is

typedef it_T std::vector<int>::iterator;
struct {
bool operator()(it_T a, it_T b) {return *a < *b;}
} comp;

sort(iv.begin(), iv.end(), comp);

Recall that using STL is very simple: define your classes and use them
immediately with standard templates.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Carl Barron
Guest





PostPosted: Fri Feb 10, 2006 11:06 am    Post subject: Re: Using local classes as functors: my first solution Reply with quote

In article <1139501386.428996.301460 (AT) o13g2000cwo (DOT) googlegroups.com>,
Maxim Yegorushkin <maxim.yegorushkin (AT) gmail (DOT) com> wrote:

Quote:
ali_tof...@hotmail.com wrote:
Hi everyone,

I've been trying to find elegant ways to use local classes as functors
and pass them to the STL algorithms. Here is my first solution. I would
appreciate any critique or thoughts on weaknesses on my approach:
\[snip]
This won't work right because of slicing. Standard algorithms take a
functor by value rather than by reference. If you made
Functor::operator() pure virtual your compiler would have complained
about the inability to create a copy of a pure virtual Functor class.

If you can live with a virtual call to operator(), which may well
prohibit inlining the call, you can make your idea work like this:

#include <functional
#include <algorithm

template<class T1, class R
struct unary_local_function
{
virtual R operator()(T1) = 0;
};

template<class T1, class R
struct unary_local_function_ref : std::unary_function<T1, R
{
unary_local_function<T1, R>* f;
unary_local_function_ref(unary_local_function<T1, R>* f) : f(f) {}
R operator()(T1 t) { return f->operator()(t); }
};

template<class T1, class R
unary_local_function_ref<T1, R> make_ref(unary_local_function<T1, R>&
f)
{
return unary_local_function_ref<T1, R>(&f);
}

int main(int ac, char** av)
{
struct functor : unary_local_function<int, int
{
int operator()(int i) { return i + 1; }
} f;

int* p = 0;
std::for_each(p, p, make_ref(f));
}

or just use boost::ref to do the same thing without writing those

templates except prehaps the base class unary_local_function.
int main()
{
struct functor:unary_local_function
{
int operator() (int i) {return i+1;}
}
functor f;
unary_local_function &fb=f;
int p[1] = {0};
for_each(&p[0],&p[1],boost::ref(&fb));
}

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Carl Barron
Guest





PostPosted: Fri Feb 10, 2006 11:06 am    Post subject: Re: Using local classes as functors: my first solution Reply with quote

In article <1139522355.433610.12060 (AT) f14g2000cwb (DOT) googlegroups.com>,
Michael Tiomkin <tmk (AT) netvision (DOT) net.il> wrote:
Quote:

The standard solution is

typedef it_T std::vector<int>::iterator;
struct {
bool operator()(it_T a, it_T b) {return *a < *b;}
} comp;

sort(iv.begin(), iv.end(), comp);

Recall that using STL is very simple: define your classes and use them
immediately with standard templates.

Functors used by the STL algorithms use arguments that are not

iterators but dereferenced values of iterators, or other objects...

struct my_less
{
bool operator () (int a,int b) const
// not bool operator () (int *a,int *b) const
// as you would imply
{
return b < a;
}
}:
int vec[]={0,1,2,3,4,5,6,7,8,9};
void test()
{
std::sort(&vec[0],&vec[10],my_less());
}

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Maxim Yegorushkin
Guest





PostPosted: Fri Feb 10, 2006 2:06 pm    Post subject: Re: Using local classes as functors: my first solution Reply with quote

Carl Barron wrote:

[]

Quote:
or just use boost::ref to do the same thing without writing those
templates except prehaps the base class unary_local_function.

Apart from errors in your code, it won't work because there is no
boost::reference_wrapper::operator().


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Maxim Yegorushkin
Guest





PostPosted: Fri Feb 10, 2006 2:06 pm    Post subject: Re: Using local classes as functors: my first solution Reply with quote

ALiX wrote:
Quote:
This won't work right because of slicing. Standard algorithms take a
functor by value rather than by reference.

Does this mean that a reference type cannot be a template argument?

It does not. But argument type deduction never ends up deducing a
reference, rather it deduces the type of an r/l-value.

Quote:
I didn't think further of it after I compiled the code using gcc. It
worked fine. It seems a little strange that the virtual call would
actually work if the object is sliced...

It worked because your base class provided an implementation of the
function, rather than leaving it pure virtual.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
ALiX
Guest





PostPosted: Fri Feb 10, 2006 5:06 pm    Post subject: Re: Using local classes as functors: my first solution Reply with quote

The code below is _not_ elegant. This is just to understand how things
work technically. Would you say that the code below would work
according to the standard?

Thanks for all the input!
/ALiX

------------------------------------------------------------
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>

using namespace std;

template<class T>
class Functor {
public:
Functor &func;
Functor(Functor &f) : func(f) {}
virtual bool operator()(T t1, T t2) {func(t1, t2);}
};

int main() {
vector<int> iv;
iv.push_back(1); iv.push_back(2); iv.push_back(3); iv.push_back(4);

struct Local_functor : public Functor<int> {
Local_functor() : Functor<int>(*this) {}
bool operator()(int i1, int i2) {return i1 > i2;}
} f;
Functor<int> g(f);

sort(iv.begin(), iv.end(), g);
copy(iv.begin(), iv.end(), ostream_iterator<int>(cout, "\n"));

return 0;
}
------------------------------------------------------------


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Ed
Guest





PostPosted: Fri Feb 17, 2006 4:06 pm    Post subject: Re: Using local classes as functors: my first solution Reply with quote

Hi ALIX, interesting bit of code. The thing I noticed is that the
Functor copy constructor is initialising the Func reference with the
argument instead of the arguments func reference. i.e.

Functor(Functor &f) : func(f.func ) {}

It seems that without doing this you will end up with all these
temporaries forming a chain which call each other all the way back to
the original one on the stack. Interesting but definatly bad.

Instead of having the g temporary why not pass the reference?

sort(iv.begin(), iv.end(), f.func);

Generally though it seems a lot simpler than the earlier version, I
dont know how boost::Ref works but I guess the application operator is
still virtual which means vptrs flying everywhere.

Maybe there is a way to remove the virtual(ness) of the operator() by
passing a member function pointer for the base class to call in its
operator() on the func reference which at that point could be cast to
the desired deriving type?

I would like to know why we cant just define functions within functions
and why dont the standerd algorithms have policies for functor copying
behaiviour?

ALiX wrote:
Quote:
The code below is _not_ elegant. This is just to understand how things
work technically. Would you say that the code below would work
according to the standard?

Thanks for all the input!
/ALiX

------------------------------------------------------------
#include <iostream
#include <vector
#include <algorithm
#include <iterator

using namespace std;

template<class T
class Functor {
public:
Functor &func;
Functor(Functor &f) : func(f) {}
virtual bool operator()(T t1, T t2) {func(t1, t2);}
};

int main() {
vector<int> iv;
iv.push_back(1); iv.push_back(2); iv.push_back(3); iv.push_back
(4);

struct Local_functor : public Functor<int> {
Local_functor() : Functor<int>(*this) {}
bool operator()(int i1, int i2) {return i1 > i2;}
} f;
Functor<int> g(f);

sort(iv.begin(), iv.end(), g);
copy(iv.begin(), iv.end(), ostream_iterator<int>(cout, "\n"));

return 0;
}
------------------------------------------------------------


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
ALiX
Guest





PostPosted: Sun Feb 19, 2006 12:06 pm    Post subject: Re: Using local classes as functors: my first solution Reply with quote

Ed wrote:
Quote:
Hi ALIX, interesting bit of code. The thing I noticed is that the
Functor copy constructor is initialising the Func reference with the
argument instead of the arguments func reference. i.e.

Functor(Functor &f) : func(f.func ) {}

It seems that without doing this you will end up with all these
temporaries forming a chain which call each other all the way back to
the original one on the stack. Interesting but definatly bad.

The reason I did that was because the Functor class holds a reference
and references must be initialized by the constructor. And isn't the
copy constructor required to take a const reference? I thought the
above code would generate a constructor that takes a Functor reference
and a default copy constructor, but now I'm not sure.

Quote:
Instead of having the g temporary why not pass the reference?

sort(iv.begin(), iv.end(), f.func);

Generally though it seems a lot simpler than the earlier version, I
dont know how boost::Ref works but I guess the application operator is
still virtual which means vptrs flying everywhere.

Maybe there is a way to remove the virtual(ness) of the operator() by
passing a member function pointer for the base class to call in its
operator() on the func reference which at that point could be cast to
the desired deriving type?

I would like to know why we cant just define functions within functions

In C++ you are allowed to call functions through function pointers and
you are allowed to return function pointers from functions. Returning
function pointers and having nested functions with access to the
surrounding function's scope leads to compiler troubles.

Quote:
and why dont the standerd algorithms have policies for functor copying
behaiviour?

/ALiX


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.