 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Guest
|
Posted: Thu Feb 09, 2006 4:06 pm Post subject: Using local classes as functors: my first solution |
|
|
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
|
Posted: Thu Feb 09, 2006 6:06 pm Post subject: Re: Using local classes as functors: my first solution |
|
|
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));
|
[]
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
|
Posted: Thu Feb 09, 2006 6:06 pm Post subject: Re: Using local classes as functors: my first solution |
|
|
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
|
Posted: Fri Feb 10, 2006 2:06 am Post subject: Re: Using local classes as functors: my first solution |
|
|
| 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
|
Posted: Fri Feb 10, 2006 3:06 am Post subject: Re: Using local classes as functors: my first solution |
|
|
| 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
|
Posted: Fri Feb 10, 2006 3:06 am Post subject: Re: Using local classes as functors: my first solution |
|
|
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
|
Posted: Fri Feb 10, 2006 11:06 am Post subject: Re: Using local classes as functors: my first solution |
|
|
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
|
Posted: Fri Feb 10, 2006 11:06 am Post subject: Re: Using local classes as functors: my first solution |
|
|
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
|
Posted: Fri Feb 10, 2006 2:06 pm Post subject: Re: Using local classes as functors: my first solution |
|
|
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
|
Posted: Fri Feb 10, 2006 2:06 pm Post subject: Re: Using local classes as functors: my first solution |
|
|
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
|
Posted: Fri Feb 10, 2006 5:06 pm Post subject: Re: Using local classes as functors: my first solution |
|
|
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
|
Posted: Fri Feb 17, 2006 4:06 pm Post subject: Re: Using local classes as functors: my first solution |
|
|
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
|
Posted: Sun Feb 19, 2006 12:06 pm Post subject: Re: Using local classes as functors: my first solution |
|
|
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 |
|
 |
|
|
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
|
|