2

ウィキペディアでこのコードを見つけました

class compare_class {
  public:
  bool operator()(int A, int B) const {
    return A < B;
  }
};
...
// Declaration of C++ sorting function.
template <class ComparisonFunctor> 
void sort_ints(int* begin_items, int num_items, ComparisonFunctor c);
...
int main() {
    int items[] = {4, 3, 1, 2};
    compare_class functor;
    sort_ints(items, sizeof(items)/sizeof(items[0]), functor);
}

最初は、ファンクターが括弧なしで sort_ints に記載されているときに、A および B パラメーターが operator()(int A, int B) にどのように渡されるのか疑問に思いました。

次に、 A と B が sort_ints 関数内の関数オブジェクトに渡されていることがわかりました。しかし、関数のアドレスを受け取っているので、sort_ints の宣言は「ComparisonFunctor c」ではなく「ComparisonFunctor* * * c」であるべきではないでしょうか?

sort_ints 関数内で、ファンクターへの関数呼び出しは次のようになりますか?

functor(*begin_items, *(begin_items+1));
4

4 に答える 4

6

パラメータを値で受け取る理由を理解するsort_intsには、コンパレータに渡されるオブジェクトが必ずしも関数ポインタではないことを覚えておく必要があります。たとえば、compare_class関数オブジェクトを使用して比較を行う場合、関数に渡すのは type の具象オブジェクトですcompare_class。はメンバー関数であり、フリー関数ではないためcompare_class::operator()、のアドレスを渡していません。operator()つまり、次のコードです。

compare_class myComparator;
myComparator(a, b);

に変換します

compare_class myComparator;
myComparator.operator() (a, b);

したがって、パラメーターは、メンバー関数へのポインターやレシーバー オブジェクトへのポインターではなく、レシーバー オブジェクトを必要とするため、ポインターではなく値でコンパレーターを取り込む必要があります。

于 2011-01-31T05:43:50.120 に答える
3

お気づきのように、sort_intsの使用法には、比較ファンクターの要件を示唆するものは何もありません。

compare_class functor;
sort_ints(items, sizeof(items)/sizeof(items[0]), functor);

sort_ints自体にも何もありません。

template <class ComparisonFunctor>
void sort_ints(int* begin_items, int num_items, ComparisonFunctor c);

また、class_compareでは、他の機能が提供されていないことを確認することによってのみ、使用される機能を推測できます。

class compare_class
{
  public:
     bool operator()(int A, int B) const { return A < B; }
};

コンパイラーは、インスタンス化された型を使用してsort_intsの実装をコンパイルしようとするまで、これがすべて一緒にハングするかどうかを判断する前に、実際にそれを残します。sort_intsには、あなたが言及した種類のステートメントが正確に含まれている必要があります。

c(*begin_items, *(begin_items+1));    // note: functor argument is "c"

だから、あなたの理解はすべての点で正しいです。ただし、Conceptsと呼ばれる提案されたC ++ 0x機能は、その実装を見ずに、sort_intの要件をより明確にすることを目的としていたことは注目に値します。残念ながら、C ++ 0xは、最適な機能を確保するための時間と経験が不十分だったため、この機能を放棄する必要がありました。うまくいけば、C++の将来のバージョンにはそのような機能が組み込まれるでしょう。ネット上で概念に関する多くの議論を見つけることができ、それらは全体的な問題をよりよく理解するのに役立つはずです。

使用したいsort_ints関数など、パズルのピースだけがあり、ComparisonFunctorの例がない場合は、sort_intsの実装を調べて、そのファンクターを作成する方法を知る必要があるため、これは重要な問題です(非常に幸運で、最新の優れたドキュメントがあります)。誤ってコードを既存の実装に依存しすぎて、sort_intの実装が少し後で変更されたときに、テストケースや他のユーザーのコードを壊さないように微妙に変更された場合でも、コードが壊れたり遅くなったりする可能性があります。期待。また、提供されているComparisonFunctorに小さな間違いがあると、sort_intの内臓のどこかから非常に複雑で紛らわしいコンパイラエラーメッセージが生成される可能性があります。s抽象化されたサービスをユーザーに提供するための良い方法ではありません。Conceptsが1日で成功することを願っています...!

于 2011-01-31T05:59:41.443 に答える
2

compare_classはクラスであることに注意してください。そのため、他のクラスを使用する方法で宣言し、関数パラメーターとして渡すことができます。

次に、compare_class実装しoperator()ます。これにより、次のことが可能になります。

compare_class obj;
obj(1, 2);

さて、上記のコード フラグメントの 2 番目のステートメントは、関数呼び出しのように見えます。したがって、ある意味では、実装するクラスの任意のオブジェクトをoperator()関数のように使用できます。

それが関数オブジェクトのポイントです。さらに、投稿で指定した同じリンクにある関数ポインターよりも他の利点があります。

編集

内部sort_ints()では、 functor は次のようなことをすることが期待されています:

for (int i = 1; i < num_items; i++)
    if (c(begin_items[i-1], begin_items[i]))
    {
        // begin_items[i-1] is less than begin_items[i], do stuff
    }
于 2011-01-31T05:41:13.550 に答える
1

それは正解です。関数呼び出し演算子は、オブジェクトのメソッドではなく、オブジェクトの名前に適用されます。さらに、関数のアドレスを渡すのではなく、オブジェクトを渡します (コピーします)。ファンクター オブジェクトにはデータ メンバーがなく、演算子 ( ) のみがあります。

于 2011-01-31T05:44:12.973 に答える