4

token位置、文、段落情報の開始/終了ペアを持つ構造が必要です。また、開始/終了ペアとして、および個別に、2つの異なる方法でメンバーにアクセスできるようにします。与えられた:

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

たとえば、次のように3つの/ペアdistance()のいずれかの間の距離を計算する関数を記述できます。startend

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.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。、、、startまたはendのいずれかにアクセスできる柔軟性が必要です。これは、パラメータとしてに渡されます。possentparamax()

これを機能させるためにいくつかのことを試みましたが(ユニオン、匿名ユニオンなどを使用して試しました)、各値を1回だけ保存しながら、双方向の柔軟性を可能にするデータ構造を思い付くことができません。

私が欲しいものを手に入れることができるように構造体を整理する方法について何かアイデアtokenはありますか?


明確化を試みる

整数のペアの構造体が与えられた場合、2つの異なる方法でデータを「スライス」できるようにしたいと思います。

  1. 特定の開始/終了ペアのメンバーへのポインターを渡すことにより、呼び出された関数がどのペアを知らなくても任意のペアで動作するようにします。発信者がどちらのペアを決定します。
  2. int特定の(つまり、任意のペアの1つのみ )のメンバーへのポインターを渡すことにより、呼び出された関数が、どちらのペアまたはどちらのペアからのものであるかを知らなくても、任意の関数で動作します。呼び出し元は、どちらのペアを決定します。intintintintint

後者の別の例は、たとえば、すべてpara.endまたはすべてを合計することsent.startです。

また、重要なのは、上記の#2の場合、発信者の負担を軽減するために、メンバーへのポインターを1つだけ渡すのが理想的です。したがって、私はユニオンを使用して何かを理解しようとしています。

#2の場合、構造体は次のように最適にレイアウトされます。

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

秘訣は、何らかの形でtokentoken2オーバーレイする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

私はバオルが与えた答えに基づいています:

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

list1つ以上のパラメーターを受け取る関数を取得します。

于 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::bindまたはboost::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 ); } );
于 2010-04-01T18:44:40.080 に答える