4

我想要一个结构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::sentor&token::para并且它会做我想做的事。因此,功能是灵活的。

但是,现在我还想编写一个函数,比如说,它计算 all或 all the或 all the等max()的最大值。pos.startpos.endsent.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. 我希望灵活地访问startend中的任何一个possent或者para将作为参数传递给max().

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

任何想法如何组织token结构以便我可以拥有我想要的东西?


试图澄清

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

  1. 通过传递一个指向特定开始/结束对的成员的指针,以便被调用的函数在不知道哪对的情况下对任何对进行操作。调用者决定哪一对。
  2. 通过传递一个指向特定成员的指针int(即,任何 int对中的一个),以便被调用的函数对任何成员进行操作,int而不知道int所说int的来自哪对或哪对。调用者决定哪一int对。

后者的另一个例子是对 allpara.end或 all求和sent.start

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

对于#2,结构将被优化布局,如:

struct token2 {
  int pos_start;
  int pos_end;
  int sent_start;
  int sent_end;
  int para_start;
  int para_end;
};

诀窍是拥有tokentoken2以某种方式覆盖 a union,但不清楚是否/如何做到这一点并满足可访问的要求。

4

4 回答 4

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;                                                                     
}                                
于 2010-04-01T18:43:31.767 回答
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和一个参数的函数。

于 2010-04-02T13:59:13.720 回答
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;
}
于 2010-04-01T18:59:31.247 回答
0

看看boost::bindorboost::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 );
}

请注意,这不是很好理解的灵活性之路:您将算法绑定到 types tokentoken::start_end并且int...

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 ); } );
于 2010-04-01T18:44:40.080 回答