如何以不同的方式访问struct成员

时间:2010-04-01 18:08:07

标签: c++ data-structures struct pointer-to-member

我希望结构token具有位置,句子和段落信息的开始/结束对。我还希望以两种不同的方式访问成员:作为开始/结束对和单独使用。给出:

struct token {
  struct start_end {
    int start;
    int end;
  };

  start_end pos;
  start_end sent;
  start_end para;

  typedef start_end token::*start_end_ptr;
};

我可以编写一个函数,比如distance(),它计算三个start / end对中的任何一个之间的距离,如:

int distance( token const &i, token const &j, token::start_end_ptr mbr ) {
  return (j.*mbr).start - (i.*mbr).end;
}

并称之为:

  token i, j;
  int d = distance( i, j, &token::pos );

将返回pos对的距离。但我也可以通过&token::sent&token::para,它可以实现我的目标。因此,该功能是灵活的。

但是,现在我还要编写一个函数,比如max(),它计算所有pos.start或所有pos.end或所有sent.start的最大值等等。

如果我添加:

  typedef int token::start_end::*int_ptr;

我可以编写如下函数:

int max( list<token> const &l, token::int_ptr p ) {
  int m = numeric_limits<int>::min();
  for ( list<token>::const_iterator i = l.begin(); i != l.end(); ++i ) {
    int n = (*i).pos.*p; // NOT WHAT I WANT: It hard-codes 'pos'
    if ( n > m )
      m = n;
  }
  return m;
}

并称之为:

  list<token> l;
  l.push_back( i );
  l.push_back( j );
  int m = max( l, &token::start_end::start );

但是,正如上面的评论所示,我不想硬编码pos。我希望startendpos sentparamax()可以灵活地访问tokenintint作为参数传递给{{1} }}

我已经尝试了几种方法来实现这一点(尝试使用工会,匿名工会等)但我无法想出一种数据结构,它允许两种方式的灵活性,同时每个值只存储一次。

任何想法如何组织int结构,以便我可以得到我想要的东西?


尝试澄清

给定整数对的结构,我希望能够以两种不同的方式“切片”数据:

  1. 通过传递特定开始/结束对的指针成员,以便被调用的函数在任何一对上运行而不知道哪一对。来电者决定哪一对。
  2. 通过传递特定int的成员指针(即,只有一个 int的任何一对),以便被调用的函数对任何{{}进行操作1}}不知道哪个int或哪个对para.end来自哪个。来电者决定哪一对sent.start
  3. 后者的另一个例子是总结所有struct token2 { int pos_start; int pos_end; int sent_start; int sent_end; int para_start; int para_end; }; 或所有token

    此外,重要的是:对于上面的#2,我理想情况下只想传递一个指向成员的指针来减轻调用者的负担。因此,我试图用工会来解决问题。

    对于#2,结构将最佳布局如下:

    token2

    诀窍是让union和{{1}}以某种方式覆盖{{1}},但是不明白是否/如何做到这一点并满足可访问的要求。

4 个答案:

答案 0 :(得分:2)

试一试。

int max( list<token> const &l,                                                  
         token::int_ptr p,                                                      
         token::start_end_ptr mbr ) {                                           
  int m = numeric_limits<int>::min();                                           
  for ( list<token>::const_iterator i = l.begin(); i != l.end(); ++i ) {        
    int n = ((*i).*mbr).*p;             
    if ( n > m )                                                                
      m = n;                                                                    
  }                                                                             
  return m;                                                                     
}                                

答案 1 :(得分:1)

我正在建立baol给出的答案:

如果我们添加一个token_reference结构和一些全局(ick!)变量,我们可以这样:

struct token_reference
{
    token::start_end_ptr start_end_ptr;
    token::int_ptr int_ptr;
};

token_reference pos_start =  { &token::pos, &token::start_end::start };
token_reference pos_end =    { &token::pos, &token::start_end::end };
token_reference sent_start = { &token::sent, &token::start_end::start };
token_reference sent_end =   { &token::sent, &token::start_end::end };
token_reference para_start = { &token::para, &token::start_end::start };
token_reference para_end =   { &token::para, &token::start_end::end };

int max( std::list<token> const &l, token_reference& ref ) {
    return max(l,ref.start_end_ptr,ref.int_ptr);
}

这样叫:

tokenList aList;
int value = max(aList,pos_start);

你得到一个带有list和另外一个参数的函数。

答案 2 :(得分:0)

查看boost::bindboost::lambda个库。或者,如果您可以使用具有C ++ 0x支持的编译器,则可能需要使用某些较新的功能,而不是手动绑定成员属性。然后你可以使用STL中提供的算法......

无论如何,这可能会做你想要的(我甚至没有花时间去尝试编译它,所以它可能不会编译):

int max( list<token> const &l, token::start_end_ptr m, token::int_ptr p ) {
  int m = numeric_limits<int>::min();
  for ( list<token>::const_iterator i = l.begin(); i != l.end(); ++i ) {
    int n = (*i).*m.*p;
    if ( n > m )
      m = n;
  }
  return m;
}
int main() {
   list<token> tks;
   int x = max( tks, &token::pos, &token::start_end::start );
}

请注意,这不是灵活理解的途径:您将算法绑定到类型tokentoken::start_endint ......

的C ++ 0x:

list <token> tks;
int the_max = 0;
for_each( tks.begin(), tks.end(), 
      [&the_max]( token const & t ) { the_max = max( the_max, t.pos.start ); } );

答案 3 :(得分:0)

struct start_end {
    int x;
    int y;
};
struct pairs {
    struct start_end a;
    struct start_end b;
}

那么我们的想法是将数据切片以动态操作X或Y吗?

 int distance(start_end m, start_end n, int member_offset){
     int val_a = *(&m + member_offset);
     int val_b = *(&n + member_offset);
     int distance = val_b - val_a; 
     return distance;
}