pointer-to-member of pair<>

S

shaun roe

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
 
T

Triple-DES

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
 
J

joseph cook

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
 
K

Kai-Uwe Bux

shaun said:
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
 
S

shaun roe

Triple-DES said:
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
 
K

Kai-Uwe Bux

shaun said:
Triple-DES said:
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
 
S

shaun roe

[snip]
}



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
 
T

Triple-DES

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
 
A

Adem24

Kai-Uwe Bux said:
Huh? Could it be that you are trying to do the job of the compilers
optimizing pass?


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());
 
K

Kai-Uwe Bux

Adem24 said:
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):


Best

Kai-Uwe Bux
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,816
Latest member
SapanaCarpetStudio

Latest Threads

Top