Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > function object for [] and *

Reply
Thread Tools

function object for [] and *

 
 
Rares Vernica
Guest
Posts: n/a
 
      06-23-2008
Hello,

I need help to replace the following code:

int *idx; //...
for (int i = 0; i < n; i++, ++out)
out = in[idx[i]];

with something like:

int *idx; //...
std::transform(idx, idx + n, out, ...);

I think the operator for transform should look something like:

__gnu_cxx::compose1(in[], *idx)

So, I think, I need a function object to apply the [] operator to "in",
given an int and another one to apply the * operator to each element in
"idx".

Thanks in advance,
Rares Vernica


 
Reply With Quote
 
 
 
 
AnonMail2005@gmail.com
Guest
Posts: n/a
 
      06-23-2008
On Jun 23, 2:22*pm, Rares Vernica <(E-Mail Removed)> wrote:
> Hello,
>
> I need help to replace the following code:
>
> * int *idx; //...
> * for (int i = 0; i < n; i++, ++out)
> * * out = in[idx[i]];
>
> with something like:
>
> * int *idx; //... * *
> * std::transform(idx, idx + n, out, ...);
>
> I think the operator for transform should look something like:
>
> * * __gnu_cxx::compose1(in[], *idx)
>
> So, I think, I need a function object to apply the [] operator to "in",
> given an int and another one to apply the * operator to each element in
> "idx".
>

Here's a first cut assuming the contents of in and out are doubles.
If they're not, change accordingly...

struct Functor
{
std::vector<double> const & m_in;

// constructor
Functor (std::vector<double> const & in) : m_in (in)
{}

// functor operator
double operator () (int i) const
{
return in [i];
}
}

std::transform (idx, idx + n, out, Functor (in));

Make sure out has enough room in out or use std::back_inserter (out).

HTH
 
Reply With Quote
 
 
 
 
Noah Roberts
Guest
Posts: n/a
 
      06-23-2008
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> On Jun 23, 2:22 pm, Rares Vernica <(E-Mail Removed)> wrote:
>> Hello,
>>
>> I need help to replace the following code:
>>
>> int *idx; //...
>> for (int i = 0; i < n; i++, ++out)
>> out = in[idx[i]];
>>
>> with something like:
>>
>> int *idx; //...
>> std::transform(idx, idx + n, out, ...);
>>
>> I think the operator for transform should look something like:
>>
>> __gnu_cxx::compose1(in[], *idx)
>>
>> So, I think, I need a function object to apply the [] operator to "in",
>> given an int and another one to apply the * operator to each element in
>> "idx".
>>

> Here's a first cut assuming the contents of in and out are doubles.
> If they're not, change accordingly...
>
> struct Functor
> {
> std::vector<double> const & m_in;
>
> // constructor
> Functor (std::vector<double> const & in) : m_in (in)
> {}
>
> // functor operator
> double operator () (int i) const
> {
> return in [i];
> }
> }
>
> std::transform (idx, idx + n, out, Functor (in));
>
> Make sure out has enough room in out or use std::back_inserter (out).
>
> HTH


You might also try something like so (untested):

std::transform(idx, idx+n, out, boost::bind(&in_type:perator[], in, _1));
 
Reply With Quote
 
Eric Pruneau
Guest
Posts: n/a
 
      06-24-2008

"Rares Vernica" <(E-Mail Removed)> a écrit dans le message de news:
(E-Mail Removed)...
> Hello,
>
> I need help to replace the following code:
>
> int *idx; //...
> for (int i = 0; i < n; i++, ++out)
> out = in[idx[i]];
>
> with something like:
>
> int *idx; //...
> std::transform(idx, idx + n, out, ...);
>
> I think the operator for transform should look something like:
>
> __gnu_cxx::compose1(in[], *idx)
>
> So, I think, I need a function object to apply the [] operator to "in",
> given an int and another one to apply the * operator to each element in
> "idx".
>
> Thanks in advance,
> Rares Vernica
>



here is a generic way to do what you want using only stl stuff.

using namespace std;

// here is the functor, I assume idx is always of type int, if not, replace
it with a template parameter

template<typename T_out, typename T_in>
struct Get : public binary_function<int, T_in, T_out>
{
// binary_function is needed by bind2nd
T_out operator()(int idx, T_in in) const
{
return in[idx];
}
};

int main()
{
int idx[3] = {0,1,2};
int in[3] = {5,4,3};
int out[3];

transform(idx, idx+3, out, bind2nd(Get<int,int*>(), &in[0]));

cout << out[0] <<"\n" <<out[1] <<"\n" <<out[2] <<"\n";
return 0;
}

this print:
5
4
3

---------------------------

Eric Pruneau


 
Reply With Quote
 
Noah Roberts
Guest
Posts: n/a
 
      06-24-2008
Eric Pruneau wrote:
> "Rares Vernica" <(E-Mail Removed)> a écrit dans le message de news:
> (E-Mail Removed)...
>> Hello,
>>
>> I need help to replace the following code:
>>
>> int *idx; //...
>> for (int i = 0; i < n; i++, ++out)
>> out = in[idx[i]];
>>
>> with something like:
>>
>> int *idx; //...
>> std::transform(idx, idx + n, out, ...);
>>
>> I think the operator for transform should look something like:
>>
>> __gnu_cxx::compose1(in[], *idx)
>>
>> So, I think, I need a function object to apply the [] operator to "in",
>> given an int and another one to apply the * operator to each element in
>> "idx".
>>
>> Thanks in advance,
>> Rares Vernica
>>

>
>
> here is a generic way to do what you want using only stl stuff.


That is good, but it should be kept in mind that boost's bind will be in
the next standard library as part of the "stl". Unless you're being
told not to use it I would definitely recommend getting it and learning
how. It's power and simplicity (as long as you're not trying to read
it) is not even remotely reached by the current library's binders.
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      06-25-2008
On Jun 23, 8:22 pm, Rares Vernica <(E-Mail Removed)> wrote:

> I need help to replace the following code:


> int *idx; //...
> for (int i = 0; i < n; i++, ++out)
> out = in[idx[i]];


> with something like:


> int *idx; //...
> std::transform(idx, idx + n, out, ...);


Why? The first is simple and easily readable. The second is
likely to be obfuscation, unless you can find a very good name
for the functional object. Unless this is a "standard"
transformation, occuring in many different places in your
application, you're almost certainly better off sticking with
the orginal loop.

At least for now. I believe that the next version of the
standard will have some sort of support for lambdas; using
transform with a lambda function here would make a lot of sense.
Moving the transformation itself out into a separate object
doesn't, however, unless that object is generally usable and can
be given a good name which reflects what it does. And trying to
simulate lambda with variations of boost::bind is probably not
going to result in anything readable.

> I think the operator for transform should look something like:


> __gnu_cxx::compose1(in[], *idx)


In other words, it should be some obscure object that many C++
programmers aren't familiar with, rather than straightforward
code which anyone can understand.

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      06-25-2008
On Jun 23, 10:34 pm, Noah Roberts <(E-Mail Removed)> wrote:
> (E-Mail Removed) wrote:
> > On Jun 23, 2:22 pm, Rares Vernica <(E-Mail Removed)> wrote:


> >> I need help to replace the following code:


> >> int *idx; //...
> >> for (int i = 0; i < n; i++, ++out)
> >> out = in[idx[i]];


> >> with something like:


> >> int *idx; //...
> >> std::transform(idx, idx + n, out, ...);


> >> I think the operator for transform should look something like:


> >> __gnu_cxx::compose1(in[], *idx)


> >> So, I think, I need a function object to apply the []
> >> operator to "in", given an int and another one to apply the
> >> * operator to each element in "idx".


> > Here's a first cut assuming the contents of in and out are
> > doubles. If they're not, change accordingly...


> > struct Functor
> > {
> > std::vector<double> const & m_in;


> > // constructor
> > Functor (std::vector<double> const & in) : m_in (in)
> > {}


> > // functor operator
> > double operator () (int i) const
> > {
> > return in [i];
> > }
> > }


> > std::transform (idx, idx + n, out, Functor (in));


> > Make sure out has enough room in out or use std::back_inserter (out).


> You might also try something like so (untested):


> std::transform(idx, idx+n, out, boost::bind(&in_type:perator[], in, _1));


Which won't work if in_type is a C style array (or a pointer).
(Otherwise, a simple, direct application of boost::bind is still
readable enough that I would consider it more or less
acceptable. Although I don't see anything wrong with the
original code, and I'd probably wait until we get lambda
expressions to upgrade it.)

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      06-25-2008
On Jun 24, 5:57 pm, Noah Roberts <(E-Mail Removed)> wrote:
> Eric Pruneau wrote:
> > "Rares Vernica" <(E-Mail Removed)> a écrit dans le message de news:
> > (E-Mail Removed)...
> >> I need help to replace the following code:


> >> int *idx; //...
> >> for (int i = 0; i < n; i++, ++out)
> >> out = in[idx[i]];


> >> with something like:


> >> int *idx; //...
> >> std::transform(idx, idx + n, out, ...);


> >> I think the operator for transform should look something like:


> >> __gnu_cxx::compose1(in[], *idx)


> >> So, I think, I need a function object to apply the []
> >> operator to "in", given an int and another one to apply the
> >> * operator to each element in "idx".


> > here is a generic way to do what you want using only stl stuff.


> That is good,


Actually, it's mostly good for obfuscation, moving the
transformation logic out of the function, and forcing the reader
to look elsewhere to know what is going on.

> but it should be kept in mind that boost's bind will be in the
> next standard library as part of the "stl". Unless you're
> being told not to use it I would definitely recommend getting
> it and learning how. It's power and simplicity (as long as
> you're not trying to read it) is not even remotely reached by
> the current library's binders.


Boost's bind definitely belongs in everyone's tool kit, but it
has it's limits as well---if the operator[] in question is the
built in version, for example, it won't work. The next version
of the standard will also include some support for lambda
expressions, which would be an even more general solution.

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

 
Reply With Quote
 
gpderetta
Guest
Posts: n/a
 
      06-25-2008
On Jun 25, 9:46*am, James Kanze <(E-Mail Removed)> wrote:
> On Jun 24, 5:57 pm, Noah Roberts <(E-Mail Removed)> wrote:
>
>
>
> > Eric Pruneau wrote:
> > > "Rares Vernica" <(E-Mail Removed)> a écrit dans le message de news:
> > > (E-Mail Removed)...
> > >> I need help to replace the following code:
> > >> *int *idx; //...
> > >> *for (int i = 0; i < n; i++, ++out)
> > >> * *out = in[idx[i]];
> > >> with something like:
> > >> *int *idx; //...
> > >> *std::transform(idx, idx + n, out, ...);
> > >> I think the operator for transform should look something like:
> > >> * *__gnu_cxx::compose1(in[], *idx)
> > >> So, I think, I need a function object to apply the []
> > >> operator to "in", given an int and another one to apply the
> > >> * operator to each element in "idx".
> > > here is a generic way to do what you want using only stl stuff.

> > That is good,

>
> Actually, it's mostly good for obfuscation, moving the
> transformation logic out of the function, and forcing the reader
> to look elsewhere to know what is going on.
>
> > but it should be kept in mind that boost's bind will be in the
> > next standard library as part of the "stl". *Unless you're
> > being told not to use it I would definitely recommend getting
> > it and learning how. *It's power and simplicity (as long as
> > you're not trying to read it) is not even remotely reached by
> > the current library's binders.

>
> Boost's bind definitely belongs in everyone's tool kit, but it
> has it's limits as well---if the operator[] in question is the
> built in version, for example, it won't work. *The next version
> of the standard will also include some support for lambda
> expressions, which would be an even more general solution.
>


It will also not work if operator[] has been overloaded for const and
non const 'this' (as it is usually the case). You need an explicit
(and ugly) cast then. The OP bind example also has a problem if used
with any container but plain arrays: bind closes its arguments by copy
so it will cause the container to be copied: use boost::ref or
boost::cref.

With boost lambda you can do:

namespace ll = boost::lambda;
std::transform(idx, idx+n, out, ll::ret<whatever>(ll::var(in)[_1]));

where 'whatever' is the result type for operator[]. In this case the
const qualified value_type of 'in' should be enough. For std::vector
(and standard containers in general) and builtin arrays, you do not
need 'ret<>':

namespace ll= boost::lambda;

std::vector<int> m = ...;
std::vector<int> idx = ...;
std::vector<int> out = ...;
std::transform(idx.begin(), idx.end(), out.begin(), ll::var(m)
[ll::_1]);

Which doesn't look that ugly.

--
gpd
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      06-25-2008
On Jun 25, 12:20 pm, gpderetta <(E-Mail Removed)> wrote:
> On Jun 25, 9:46 am, James Kanze <(E-Mail Removed)> wrote:


[...]
> > Boost's bind definitely belongs in everyone's tool kit, but it
> > has it's limits as well---if the operator[] in question is the
> > built in version, for example, it won't work. The next version
> > of the standard will also include some support for lambda
> > expressions, which would be an even more general solution.


> It will also not work if operator[] has been overloaded for const and
> non const 'this' (as it is usually the case). You need an explicit
> (and ugly) cast then.


Good point.

> The OP bind example also has a problem if used
> with any container but plain arrays: bind closes its arguments by copy
> so it will cause the container to be copied: use boost::ref or
> boost::cref.


> With boost lambda you can do:


> namespace ll = boost::lambda;
> std::transform(idx, idx+n, out, ll::ret<whatever>(ll::var(in)[_1]));


> where 'whatever' is the result type for operator[]. In this case the
> const qualified value_type of 'in' should be enough. For std::vector
> (and standard containers in general) and builtin arrays, you do not
> need 'ret<>':


> namespace ll= boost::lambda;
>
> std::vector<int> m = ...;
> std::vector<int> idx = ...;
> std::vector<int> out = ...;
> std::transform(idx.begin(), idx.end(), out.begin(), ll::var(m)
> [ll::_1]);


> Which doesn't look that ugly.


No. I didn't consider boost::lambda, because it seems that
every time I try it on something real, I hit up against some
limitations of it, and end up having to add extra qualifiers,
etc., in order to make it work. Of course, your ll::var would
qualify there, but in this case, I guess the rest of the
expression is simple enough that it doesn't feel too bothersome.

In general, I think real support for lambdas (at the language
level) should open up a lot of possibilities along these lines.

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
function Object,function statement,function operator alex Javascript 3 12-28-2006 02:57 PM
Object creation - Do we really need to create a parent for a derieved object - can't the base object just point to an already created base object jon wayne C++ 9 09-22-2005 02:06 AM
write a function such that when ever i call this function in some other function .it should give me tha data type and value of calling function parameter komal C++ 6 01-25-2005 11:13 AM
How to get the object ids of all the tables and use them to invoke a function of the object. Eshrath Ali Khan Javascript 1 11-09-2004 09:35 AM
Passing a C++ object's member function to a C function expecing a function pointer! James Vanns C++ 7 01-21-2004 02:39 AM



Advertisments