如何以不同方式访问结构成员
我想要一个结构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
。我希望能够灵活地访问 pos
、sent
或 para 中任何一个的
将作为参数传递给 start
或 end
max()
。
我已经尝试了几种方法来使其工作(尝试使用联合、匿名联合等),但我无法想出一种数据结构,该数据结构允许双向灵活性,同时每个值仅存储一次。
有什么想法如何组织 token
结构,以便我可以获得我想要的东西吗?
尝试澄清
给定整数对的结构,我希望能够以两种不同的方式“切片”数据:
- 通过传递指向特定开始/结束对的成员的指针,以便被调用的函数对任何对进行操作不知道是哪一对。呼叫者决定哪一对。
- 通过传递指向特定
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;
};
技巧是让 token
和 token2
以某种方式用 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:
- 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.
- By passing a pointer-to-member of a particular
int
(i.e., only oneint
of any pair) so that the called function operates on anyint
without knowing either whichint
or which pair saidint
is from. The caller decides whichint
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
只是尝试一下。
Just a try.
我正在构建答案 baol 给出:
如果我们添加一个
token_reference
结构和一些全局(讨厌!)变量,我们可以这样:像这样调用:
你会得到一个带有
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:called like this:
you get a function taking a
list
and one more parameter.查看
boost::bind
或boost::lambda
库。或者,如果您可以使用支持 C++0x 的编译器,您可能希望使用一些较新的功能,而不是手动绑定成员属性。然后你可以使用STL中提供的算法...无论如何,这可能可以做你想做的事(我什至没有花时间尝试编译它,所以它也可能不编译):
请注意,这不是通向灵活性的路径很好理解:您将算法绑定到类型
token
、token::start_end
和int
...C++0x :
Take a look at the
boost::bind
orboost::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):
Note that this is not the path to flexibility well understood: you are binding the algorithm to the types
token
,token::start_end
andint
...C++0x:
那么这个想法是对数据进行切片以动态地对 X 或 Y 进行操作吗?
so is the idea is to slice the data to operate on X's or Y's dynamically?