0

関数呼び出し()もオーバーロードされる可能性があることを読みました。http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B

次はどういう意味ですか?

できます。

template<typename T, typename Comp>
struct bind{
    T v;
    Comp comp;
    bool operator()(const T& b){
        return comp(b,v);
    }
};

int main(){
    bind<int, less<int> > b;
    b.v = 2;
    cout << b(3) << "\n";
}
4

3 に答える 3

2

これは、タイプのオブジェクトを作成する場合、bind<>そのオブジェクトに関数呼び出し演算子を適用できることを意味します。

このような:

bind<int, std::less<int>> b;
b.v = 2;
std::cout << b(1) << "\n";

そのスニペットは、標準出力に「true」と出力される場合があります。

于 2013-02-15T20:40:12.993 に答える
1

現状では、「構文エラー」以外の意味はほとんどありません。例えば:

template<T, Op>

これは単に許可されていません。テンプレート パラメーターごとに、型 (classまたはを使用typename) か、 などの型以外のパラメーターかを指定する必要がありますint。明らかな意図は、これらの両方が型パラメーターであるべきであるため、次のようなものが必要です。

template <class T, class Op>

また:

template <typename T, typename Op>

classこの状況では、との間に意味の違いはありませんtypename

struct bind{
    T v;

初期化されていないままにしておくと、未定義vの動作が発生するため、おそらく許可したくないでしょう。通常は、パラメーターとして T を受け取り、その値に初期化するコンストラクターを追加することで、これを防ぐことができvます。

bind(T const &v) : v(v) {}

このようなコンストラクターを含めると、コンパイラーはデフォルトのコンストラクターを自動的に生成しないため、初期化されていないbindオブジェクトを作成することはできなくなりますv。まさに私たちが望んでいたものです。

compオブジェクトを作成していますが:

Op comp;

かなり無害ですが、不要でもあります。で作成された一時インスタンスと比較することもできますOp()。その場合は次のようになります。

bool operator()(const T& a){
    return comp(a,v);
}

...次のようになります(そしてOp comp;単に削除されます):

bool operator()(T const &a) { 
    return Op()(a, v);
}

修正があっても、このコードは時代遅れだと思います。C++98/03 では、次のようなアルゴリズムにファンクターを提供する必要がある状況で役立ちました。

std::remove_copy_if(a.begin(), a.end(), bind<int, 
                    std::back_inserter(b),
                    bind<int, std::less<int> >(5));

... から までの数値をコピーab、5 未満の数値を削除します。

ただし、C++11 では、これのほとんど (すべてではないにしても) の使用はbindおそらく代わりにラムダとして記述される必要があるため、上記のビットは次のようになります。

std::remove_copy_if(a.begin(), a.end(), bind<int, 
                    std::back_inserter(b),
                    [](int x) { return x < 5; });

これは短いだけでなく、(少なくとも慣れれば)関数を使用std::lessbindてまとめるよりもかなり簡単です。通常、実行時の効率に違いはありません。ラムダは基本的に、クラス テンプレートを生成する「省略形」の方法であるため、ラムダが生成するものは、bind.

于 2013-02-15T21:07:23.083 に答える
1

というクラスがある場合fooは、その型のオブジェクトのメンバー関数を呼び出すことの意味を理解していると思います。

foo f;
f.bar();

また、特定の操作をオーバーロードできることも理解できます。たとえば、次のようなことができるように、operator+for をオーバーロードできます。foo

foo f, g;
f + g;

クラスをオーバーロードすることもoperator()できるようになりました。これにより、関数であるかのように呼び出すことができます。

foo f;
f();

はい、f関数ではありませんが、オーバーロードするクラス型のオブジェクトですoperator()。これを行うクラス型は、ファンクターまたは関数オブジェクトとして知られています。

あなたが与えた例でbindは、ファンクターです。そのタイプのオブジェクトを作成すると、関数のように呼び出すことができ、a を渡すと、aconst T&bool返されます。の実装は、operator()に格納されている関数を実際に呼び出し、に渡したオブジェクトと 型のメンバ オブジェクトのcomp両方を渡しTます。operator()avT

于 2013-02-15T20:44:01.170 に答える