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 operator() as return a reference to class self

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





PostPosted: Wed Jun 21, 2006 2:56 pm    Post subject: Using operator() as return a reference to class self Reply with quote



Overload operator() is magic in C++, since you can implement
a functor using operator(), the behave like a normal function.
I found we can use a trick that operator() return a reference to
class self. According return value, we can do a recursive call
operator(), this idiom can be used to initialize a list like class,
such as list, deque, vector...
There is an example:

#include <list>
#include <iostream>
#include <iterator>
#include <algorithm>

template<typename T>
class cmlist : public std::list<T>
{
public:
// Note: here *MUST* return a reference to class self
cmlist& operator()(const T& e)
{
this->push_back(e);

return *this;
}
};

int main()
{
cmlist<int> il;

// Note: using recursive call operator to
// initialize the list.
// avoid using 3 line to call 3 push_back()
il(3)(4)(5);

std::copy(il.begin(),
il.end(),
std::ostream_iterator<int>(std::cout, " "));

return 0;
}

Any suggestion?

--
Regards.
Mockey Chen

[ 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: Thu Jun 22, 2006 4:01 pm    Post subject: Re: Using operator() as return a reference to class self Reply with quote



In article <e792fd$7s0$1 (AT) news (DOT) yaako.com>, Mockey Chen
<mockey.chen (AT) google (DOT) com> wrote:

Quote:
Overload operator() is magic in C++, since you can implement
a functor using operator(), the behave like a normal function.
I found we can use a trick that operator() return a reference to
class self. According return value, we can do a recursive call
operator(), this idiom can be used to initialize a list like class,
such as list, deque, vector...
There is an example:

#include <list
#include <iostream
#include <iterator
#include <algorithm

template<typename T
class cmlist : public std::list<T
{
public:
// Note: here *MUST* return a reference to class self
cmlist& operator()(const T& e)
{
this->push_back(e);

return *this;
}
};

int main()
{
cmlist<int> il;

// Note: using recursive call operator to
// initialize the list.
// avoid using 3 line to call 3 push_back()
il(3)(4)(5);

std::copy(il.begin(),
il.end(),
std::ostream_iterator<int>(std::cout, " "));

return 0;
}


I don't recommend inheritance from classes without a
virtual destructor. I use an overloaded operator << to
do this. If I have a custom container class I see no major
problem.

I prefer an overload of operator << to do this in general.
The only problem with a simple template solution like
template <class T,class A,class X>
inline
std::list<T,A> & operator << (std::list<T,A> &list,const X &x)
{
list.push_back(x);
return *this;
}

occurs if X is in namespace std, but this can be handle with a wrapper
struct containing a const X &.

template <class X>
struct class_wrapper
{
const X &x;
class_wrapper(const X & a)Mad(a){}
operator const X &() {return x;}
};

template <class X>
inline class_wrapper<X> wrap_class(const X &x)
{ return class_wrapper<X>(x);}

and using wrap_class(x) as the args of the << chain.

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






PostPosted: Thu Jun 22, 2006 4:02 pm    Post subject: Re: Using operator() as return a reference to class self Reply with quote



Mockey Chen wrote:
....
Quote:
There is an example:

....
template<typename T
class cmlist : public std::list<T
{
public:
// Note: here *MUST* return a reference to class self
cmlist& operator()(const T& e)
{
this->push_back(e);

return *this;
}
};

int main()
{
cmlist<int> il;

// Note: using recursive call operator to
// initialize the list.
// avoid using 3 line to call 3 push_back()
il(3)(4)(5);

return 0;
}

Any suggestion?


Yes - boost assignment library:
http://www.boost.org/libs/assign/index.html
It does what you are suggesting, using that trick and many more.

Quote:
--
Regards.
Mockey Chen


Tony


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





PostPosted: Fri Jun 23, 2006 3:03 pm    Post subject: Re: Using operator() as return a reference to class self Reply with quote

Mockey Chen wrote:
Quote:
Overload operator() is magic in C++, since you can implement
a functor using operator(), the behave like a normal function.
I found we can use a trick that operator() return a reference to
class self. According return value, we can do a recursive call
operator(), this idiom can be used to initialize a list like class,
such as list, deque, vector...
There is an example:

template<typename T
class cmlist : public std::list<T
{
public:
// Note: here *MUST* return a reference to class self
cmlist& operator()(const T& e)
{
this->push_back(e);

return *this;
}
};

Since the std collections aren't really designed to be publicly
inherited from, I would do one of two things. If I wanted my own types
that did what the std ones do with some extras, I would privately
inherit the class (this prevents someone from casting my class to the
std one and thinking that if they delete that class, my class would be
cleaned up too) and export the methods I wanted with a 'using'
statement. If I didn't want that, then I would write my class as a
wrapper which accepts a std collection as its initializer and then
initialized that. My wrapper could then disappear and the user would
use the std collection everywhere.

I haven't actually compiled this, but it might look like

template<typename C>
class InitializeIt {
public:
typedef InitializeIt<C> _Self;
typedef typename C::value_type value_type;

InitializeIt(C & c) : m_c(c) {}
_Self & operator()(value_type const & v) {
m_c.push_back(v);
return *this;
}
private:
C & m_c;
};

int main(int, char **)
{
std::list<int> l;
InitializeIt<std::list<int> > i(l);
i(5)(6)(6)(Cool;

std::copy(l.begin(),
l.end(),
std::ostream_iterator<int>(std::cout, " "));
}

This accomplishes the same thing without introducing a new set of
types.

Hope that helps,
joe


[ 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.