如何以不同方式访问结构成员

发布于 2024-08-27 18:57:00 字数 2542 浏览 3 评论 0原文

我想要一个结构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。我希望能够灵活地访问 possentpara 中任何一个的 startend 将作为参数传递给 max()

我已经尝试了几种方法来使其工作(尝试使用联合、匿名联合等),但我无法想出一种数据结构,该数据结构允许双向灵活性,同时每个值仅存储一次。

有什么想法如何组织 token 结构,以便我可以获得我想要的东西吗?


尝试澄清

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

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

后者的另一个例子是对所有 para.end 或所有 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 以某种方式用 union 覆盖,但它是尚不清楚是否/如何可以做到这一点并满足可访问的要求。

I want to have a structure token that has start/end pairs for position, sentence, and paragraph information. I also want the members to be accessible in two different ways: as a start/end pair and individually. Given:

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;
};

I can write a function, say distance(), that computes the distance between any of the three start/end pairs like:

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

and call it like:

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

that will return the distance of the pos pair. But I can also pass &token::sent or &token::para and it does what I want. Hence, the function is flexible.

However, now I also want to write a function, say max(), that computes the maximum value of all the pos.start or all the pos.end or all the sent.start, etc.

If I add:

  typedef int token::start_end::*int_ptr;

I can write the function like:

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;
}

and call it like:

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

However, as indicated in the comment above, I do not want to hard-code pos. I want the flexibility of accessible the start or end of any of pos, sent, or para that will be passed as a parameter to max().

I've tried several things to get this to work (tried using unions, anonymous unions, etc.) but I can't come up with a data structure that allows the flexibility both ways while having each value stored only once.

Any ideas how to organize the token struct so I can have what I want?


Attempt at clarification

Given struct of pairs of integers, I want to be able to "slice" the data in two distinct ways:

  1. By passing a pointer-to-member of a particular start/end pair so that the called function operates on any pair without knowing which pair. The caller decides which pair.
  2. By passing a pointer-to-member of a particular int (i.e., only one int of any pair) so that the called function operates on any int without knowing either which int or which pair said int is from. The caller decides which int of which pair.

Another example for the latter would be to sum, say, all para.end or all sent.start.

Also, and importantly: for #2 above, I'd ideally like to pass only a single pointer-to-member to reduce the burden on the caller. Hence, me trying to figure something out using unions.

For #2, the struct would be optimally laid out like:

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

The trick is to have token and token2 overlaid somehow with a union, but it's not apparent if/how that can be done and yet satisfy the accessible requirements.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

手长情犹 2024-09-03 18:57:00

只是尝试一下。

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;                                                                     
}                                

Just a try.

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;                                                                     
}                                
允世 2024-09-03 18:57:00

我正在构建答案 baol 给出:

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

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 和一个的函数更多参数。

I'm building upon the answer baol gave:

If we add a token_reference struct and some global (ick!) variables we can have this:

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);
}

called like this:

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

you get a function taking a list and one more parameter.

反目相谮 2024-09-03 18:57:00

查看 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 ); } );

Take a look at the boost::bind or boost::lambda libraries. Or if you can use a compiler with C++0x support you might want to use some of the newer features instead of manually binding the member attributes. And then you can use the algorithms provided in the STL...

Anyway this can possibly do what you want (I did not even take time to try and compile it, so it might as well not compile):

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 );
}

Note that this is not the path to flexibility well understood: you are binding the algorithm to the types token, token::start_end and 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 ); } );
谜兔 2024-09-03 18:57:00
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;
}
struct start_end {
    int x;
    int y;
};
struct pairs {
    struct start_end a;
    struct start_end b;
}

so is the idea is to slice the data to operate on X's or Y's dynamically?

 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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文