Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   pointer-to-member of pair<> (http://www.velocityreviews.com/forums/t619625-pointer-to-member-of-pair.html)

shaun roe 06-11-2008 09:32 AM

pointer-to-member of pair<>
 
Question about pointer-to-data members

I have a deeply nested loop, the innermost bit looks a little like this:

for(it(vec.begin(), end(vec.end()), it!=end;++it){
if (global == 0){
myObj = it->func().second->anObj();
} else {
myObj = it->func().first->anObj();
}
myVec.push_back(anObj);
}

where it->func() returns a pair of objects' pointers with 'anObj' functions which return an object
suitable for insertion in myVec.

Now, given that 'global' is known before I enter any loops, I could in principle decide to use the
'first' or 'second' before I ever enter this loop, instead of deciding inside the loop (and
hopefully thus save a few ns of time)... I thought to use a pointer-to-member (the member being
'first' or 'second') but cannot figure out the syntax.
This is what I am trying:

const primaryObj * pair<const primaryObj *, const primaryObj *>::*pFirstOrSecond;
pFirstOrSecond = global? (&pair<const primaryObj *,const primaryObj *>::first):(pair<const
primaryObj *,const primaryObj *>::second);

the compiler complains :

.../src/SCTHitsNoiseMonTool.cxx: In member function `StatusCode
SCTHitsNoiseMonTool::generalHistsandNoise()':
/usr/lib/gcc/x86_64-redhat-linux/3.4.6/../../../../include/c++/3.4.6/bits/stl_pair.h:74: error:
object missing in reference to `std::pair<const Trk::PrepRawData*, const Trk::PrepRawData*>::second'

where Trk::PrepRawData corresponds to 'primaryObj' in the example above, as if it is looking for the
concrete object rather than the generic pointer-to-member.

can anyone help?

cheers
shaun

Triple-DES 06-11-2008 12:26 PM

Re: pointer-to-member of pair<>
 
On 11 Jun, 11:32, shaun roe <shaun....@wanadoo.fr> wrote:
> Question about pointer-to-data members
>
> I have a deeply nested loop, the innermost bit looks a little like this:
>
> for(it(vec.begin(), end(vec.end()), it!=end;++it){
> * if (global == 0){
> * * myObj = it->func().second->anObj();
> * } else {
> * * myObj = it->func().first->anObj();
> * }
> * myVec.push_back(anObj);
>
> }
>
> where it->func() returns a pair of objects' pointers with 'anObj' functions which return an object
> suitable for insertion in myVec.
>
> Now, given that 'global' is known before I enter any loops, I could in principle decide to use the
> 'first' or 'second' before I ever enter this loop, instead of deciding inside the loop (and
> hopefully thus save a few ns of time)... I thought to use a pointer-to-member (the member being
> 'first' or 'second') but cannot figure out the syntax.
> This is what I am trying:
>
> *const primaryObj * pair<const primaryObj *, const primaryObj *>::*pFirstOrSecond;
> * *pFirstOrSecond = global? (&pair<const primaryObj *,const primaryObj *>::first):(pair<const
> primaryObj *,const primaryObj *>::second);
>
> the compiler complains :

[snip]
> can anyone help?


I think I understand what you are trying to do, but I don't think it's
possible, because there is no special "pointer to data-member".

Such a pointer would on most implementations be equivalent to the byte
offset from the beginning of the object's data structure to the data
member, IOW very similar to the "offsetof" macro.

However, you can't (formally) use offsetof on a pair, because it is
not strictly POD (it has a user-declared ctor). It would still
probably work on most implementations.

Other options include writing the loop twice:
if(global == 0)
// entire loop
else
// entire loop

Or rewrite the loop using functors to fetch the object, something like
this:

if(global == 0)
std::transform(vec.begin(), vec.end(), std::back_inserter(myVec),
get1st());
else
std::transform(vec.begin(), vec.end(), std::back_inserter(myVec),
get2nd());

Which may or may not be faster than the original loop ;)

DP

joseph cook 06-11-2008 12:39 PM

Re: pointer-to-member of pair<>
 
On Jun 11, 5:32*am, shaun roe <shaun....@wanadoo.fr> wrote:
> Question about pointer-to-data members
>
> I have a deeply nested loop, the innermost bit looks a little like this:
>
> for(it(vec.begin(), end(vec.end()), it!=end;++it){
> * if (global == 0){
> * * myObj = it->func().second->anObj();
> * } else {
> * * myObj = it->func().first->anObj();
> * }
> * myVec.push_back(anObj);
>
> }


> can anyone help?


I think you are heading into Knuthian territory here, but, perhaps you
could add:
it->funcFirst() and it->funcSecond()

Then outside the loop create a pointer to one or the other of these
functions (since I presume they have the same signature).

Then you _could_ use this pointer to member function inside the loop.

Joe Cook



Kai-Uwe Bux 06-11-2008 01:03 PM

Re: pointer-to-member of pair<>
 
shaun roe wrote:

> Question about pointer-to-data members
>
> I have a deeply nested loop, the innermost bit looks a little like this:
>
> for(it(vec.begin(), end(vec.end()), it!=end;++it){


Huh? Could it be that you are trying to do the job of the compilers
optimizing pass?

> if (global == 0){
> myObj = it->func().second->anObj();
> } else {
> myObj = it->func().first->anObj();
> }
> myVec.push_back(anObj);
> }
>
> where it->func() returns a pair of objects' pointers with 'anObj'
> functions which return an object suitable for insertion in myVec.
>
> Now, given that 'global' is known before I enter any loops, I could in
> principle decide to use the 'first' or 'second' before I ever enter this
> loop, instead of deciding inside the loop (and hopefully thus save a few
> ns of time)...


So what is wrong with

if ( global == 0 ) {
// use second fields
for(it(vec.begin(), end(vec.end()), it!=end;++it){
myVec.push_back( it->func().second->anObj() );
}
else {
// use first fields
for(it(vec.begin(), end(vec.end()), it!=end;++it){
myVec.push_back( it->func().first->anObj() );
}
}


[snip]


Best

Kai-Uwe Bux

shaun roe 06-11-2008 09:03 PM

Re: pointer-to-member of pair<>
 
In article
<d7f7c277-fe57-4263-b29f-24410deb747f@d77g2000hsb.googlegroups.com>,
Triple-DES <DenPlettfrie@gmail.com> wrote:

> On 11 Jun, 11:32, shaun roe <shaun....@wanadoo.fr> wrote:
> > Question about pointer-to-data members
> >
> > I have a deeply nested loop, the innermost bit looks a little like this:
> >
> > for(it(vec.begin(), end(vec.end()), it!=end;++it){
> > * if (global == 0){
> > * * myObj = it->func().second->anObj();
> > * } else {
> > * * myObj = it->func().first->anObj();
> > * }
> > * myVec.push_back(anObj);
> >
> > }
> >

[snip]
>
> I think I understand what you are trying to do, but I don't think it's
> possible, because there is no special "pointer to data-member".


ok, thanks... I'm using 'C++ Common Knowledge',S. C. Dewhurst, Item 15
:Pointers to Class Members Are Not Pointers
as a reference, where I see:
class C{
public:
int a_;
};
intC::*pimC;
C aC;
C *pC = &aC;
aC.*pimC=0;
int b=pC->*pimC;

so I was hoping to do the same for a pair; however If I understand your
comment below, this is not possible where there is a non-trivial
constructor...this is an important caveat!

cheers
s

>
> Such a pointer would on most implementations be equivalent to the byte
> offset from the beginning of the object's data structure to the data
> member, IOW very similar to the "offsetof" macro.
>
> However, you can't (formally) use offsetof on a pair, because it is
> not strictly POD (it has a user-declared ctor). It would still
> probably work on most implementations.
>
> Other options include writing the loop twice:
> if(global == 0)
> // entire loop
> else
> // entire loop
>
> Or rewrite the loop using functors to fetch the object, something like
> this:
>
> if(global == 0)
> std::transform(vec.begin(), vec.end(), std::back_inserter(myVec),
> get1st());
> else
> std::transform(vec.begin(), vec.end(), std::back_inserter(myVec),
> get2nd());
>
> Which may or may not be faster than the original loop ;)
>
> DP


Kai-Uwe Bux 06-11-2008 09:26 PM

Re: pointer-to-member of pair<>
 
shaun roe wrote:

> In article
> <d7f7c277-fe57-4263-b29f-24410deb747f@d77g2000hsb.googlegroups.com>,
> Triple-DES <DenPlettfrie@gmail.com> wrote:
>
>> On 11 Jun, 11:32, shaun roe <shaun....@wanadoo.fr> wrote:
>> > Question about pointer-to-data members
>> >
>> > I have a deeply nested loop, the innermost bit looks a little like
>> > this:
>> >
>> > for(it(vec.begin(), end(vec.end()), it!=end;++it){
>> > if (global == 0){
>> > myObj = it->func().second->anObj();
>> > } else {
>> > myObj = it->func().first->anObj();
>> > }
>> > myVec.push_back(anObj);
>> >
>> > }
>> >

> [snip]
>>
>> I think I understand what you are trying to do, but I don't think it's
>> possible, because there is no special "pointer to data-member".

>
> ok, thanks... I'm using 'C++ Common Knowledge',S. C. Dewhurst, Item 15
> :Pointers to Class Members Are Not Pointers
> as a reference, where I see:
> class C{
> public:
> int a_;
> };
> intC::*pimC;
> C aC;
> C *pC = &aC;
> aC.*pimC=0;
> int b=pC->*pimC;


What's stopping you?

#include <utility>
#include <iostream>

typedef std::pair<int,int> int_pair;
typedef int int_pair::* int_member_ptr;

int main ( void ) {
int_member_ptr ptr1 = &int_pair::first;
int_member_ptr ptr2 = &int_pair::second;
int_pair the_pair ( 2, 3 );
std::cout << the_pair.*ptr1 << '\n';
std::cout << the_pair.*ptr2 << '\n';
}


> so I was hoping to do the same for a pair; however If I understand your
> comment below, this is not possible where there is a non-trivial
> constructor...this is an important caveat!


Huh?

The real problem is that for pair<T,S>, this will not work since the pointer
has to point to T or to S. Thus, stuff like this can only be done for
a "diagonal" pair<T,T>.



Best

Kai-Uwe Bux

shaun roe 06-12-2008 05:22 AM

Re: pointer-to-member of pair<>
 
In article <g2pftr$7pu$1@aioe.org>, Kai-Uwe Bux <jkherciueh@gmx.net>
wrote:
[snip]
>
> }
>
>
> > so I was hoping to do the same for a pair; however If I understand your
> > comment below, this is not possible where there is a non-trivial
> > constructor...this is an important caveat!

>
> Huh?
>
> The real problem is that for pair<T,S>, this will not work since the pointer
> has to point to T or to S. Thus, stuff like this can only be done for
> a "diagonal" pair<T,T>.
>
>
>
> Best
>
> Kai-Uwe Bux


Indeed I have a 'diagonal' pair, the only structural difference is that
they are const pointers, so I must be awry somewhere in my syntax...
I'll try harder with a simpler example and come back if that doesnt work!

thanks

shaun

Triple-DES 06-12-2008 05:40 AM

Re: pointer-to-member of pair<>
 
On 11 Jun, 23:03, shaun roe <shaun....@wanadoo.fr> wrote:
> >*Triple-DES <DenPlettf...@gmail.com> wrote:
> > I think I understand what you are trying to do, but I don't think it's
> > possible, because there is no special "pointer to data-member".


From your citation, it is obvious that this is just plain wrong. At
least my description of its implementation is fairly accurate.

[snip]

> so I was hoping to do the same for a pair; however If I understand your
> comment below, this is not possible where there is a non-trivial
> constructor...this is an important caveat!


Yes, this is true for the offsetof macro. It is however not true for
pointers to class members (see Kai-Uwe's post). Note that I still
think using std::transform is the most elegant way of accomplishing
your task :)

DP

Adem24 06-19-2008 08:14 PM

Re: pointer-to-member of pair<>
 
"Kai-Uwe Bux" <jkherciueh@gmx.net> wrote
> shaun roe wrote:
>
> > Question about pointer-to-data members
> >
> > I have a deeply nested loop, the innermost bit looks a little like this:
> >
> > for(it(vec.begin(), end(vec.end()), it!=end;++it){

>
> Huh? Could it be that you are trying to do the job of the compilers
> optimizing pass?
>
> > if (global == 0){
> > myObj = it->func().second->anObj();
> > } else {
> > myObj = it->func().first->anObj();
> > }
> > myVec.push_back(anObj);
> > }
> >
> > where it->func() returns a pair of objects' pointers with 'anObj'
> > functions which return an object suitable for insertion in myVec.
> >
> > Now, given that 'global' is known before I enter any loops, I could in
> > principle decide to use the 'first' or 'second' before I ever enter this
> > loop, instead of deciding inside the loop (and hopefully thus save a few
> > ns of time)...

>
> So what is wrong with
>
> if ( global == 0 ) {
> // use second fields
> for(it(vec.begin(), end(vec.end()), it!=end;++it){
> myVec.push_back( it->func().second->anObj() );
> }
> else {
> // use first fields
> for(it(vec.begin(), end(vec.end()), it!=end;++it){
> myVec.push_back( it->func().first->anObj() );
> }
> }


I'd do it as follows:

for(it(vec.begin(), end(vec.end()), it!=end;++it)
myVec.push_back(!global ? it->func().second->anObj() : it->func().first->anObj());



Kai-Uwe Bux 06-19-2008 08:38 PM

Re: pointer-to-member of pair<>
 
Adem24 wrote:

> "Kai-Uwe Bux" <jkherciueh@gmx.net> wrote
>> shaun roe wrote:
>>
>> > Question about pointer-to-data members
>> >
>> > I have a deeply nested loop, the innermost bit looks a little like
>> > this:
>> >
>> > for(it(vec.begin(), end(vec.end()), it!=end;++it){

>>
>> Huh? Could it be that you are trying to do the job of the compilers
>> optimizing pass?
>>
>> > if (global == 0){
>> > myObj = it->func().second->anObj();
>> > } else {
>> > myObj = it->func().first->anObj();
>> > }
>> > myVec.push_back(anObj);
>> > }
>> >
>> > where it->func() returns a pair of objects' pointers with 'anObj'
>> > functions which return an object suitable for insertion in myVec.
>> >
>> > Now, given that 'global' is known before I enter any loops, I could in
>> > principle decide to use the 'first' or 'second' before I ever enter
>> > this loop, instead of deciding inside the loop (and hopefully thus save
>> > a few ns of time)...

>>
>> So what is wrong with
>>
>> if ( global == 0 ) {
>> // use second fields
>> for(it(vec.begin(), end(vec.end()), it!=end;++it){
>> myVec.push_back( it->func().second->anObj() );
>> }
>> else {
>> // use first fields
>> for(it(vec.begin(), end(vec.end()), it!=end;++it){
>> myVec.push_back( it->func().first->anObj() );
>> }
>> }

>
> I'd do it as follows:
>
> for(it(vec.begin(), end(vec.end()), it!=end;++it)
> myVec.push_back(!global ? it->func().second->anObj() :
> it->func().first->anObj());


You don't like white space, do you?

Note that the OP specifically intended to pull the check for global out of
the loop (you even quoted that):

>> > Now, given that 'global' is known before I enter any loops, I could in
>> > principle decide to use the 'first' or 'second' before I ever enter
>> > this loop, instead of deciding inside the loop (and hopefully thus save
>> > a few ns of time)...



Best

Kai-Uwe Bux


All times are GMT. The time now is 09:54 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.