5

次のスニペットの何が問題になっていますか?

#include <tr1/functional>
#include <functional>
#include <iostream>

using namespace std::tr1::placeholders;

struct abc
{
    typedef void result_type;

    void hello(int)
    { std::cout << __PRETTY_FUNCTION__ << std::endl; }

    void hello(int) const
    { std::cout << __PRETTY_FUNCTION__ << std::endl; }

    abc()
    {}
};

int
main(int argc, char *argv[])
{
    const abc x;
    int a = 1;

    std::tr1::bind(&abc::hello, x , _1)(a);
    return 0;
}

g++-4.3 でコンパイルしようとすると、cv -qualifier オーバーロードされた関数が両方tr1::mem_fn<>を混同tr1::bind<>し、次のエラーが発生するようです。

no matching function for call to ‘bind(<unresolved overloaded function type>,...

代わりに、次のスニペットはコンパイルされますが、const-correctnessが壊れているようです:

struct abc
{
    typedef void result_type;

    void operator()(int)
    { std::cout << __PRETTY_FUNCTION__ << std::endl; }

    void operator()(int) const
    { std::cout << __PRETTY_FUNCTION__ << std::endl; }

    abc()
    {}
};

...

    const abc x;
    int a = 1;
    std::tr1::bind( x , _1)(a);

どんな手掛かり?

4

3 に答える 3

4

constness が不明なときにルックアップが行われthisます。キャストでヒントを与えるだけです。これを試して:

typedef void (abc::*fptr)(int) const; // or remove const
std::tr1::bind((fptr)&abc::hello, x , _1)(a);

ここで、静止画の削除が機能することにも気付くかもしれませんconst。これは、x をポインターで渡す必要があるためです (C++ メンバー関数の最初の引数である暗黙thisパラメーターは常にポインターであるため)。代わりにこれを試してください:

typedef void (abc::*fptr)(int) const; // won't compile without const (good!)
std::tr1::bind((fptr)&abc::hello, &x , _1)(a);

以下の私のコメント内で発見されたように、最初に行ったようにを省略すると、 xを value&で渡すことになりますが、これは通常、必要なものではありません (ただし、特定の例では実際的な違いはほとんどありません)。これは実際には、 にとって不幸な落とし穴のように思えます。bind

于 2008-11-21T22:03:50.523 に答える
1

この質問は回答済みですが、バインドでオーバーロードを指定する最良の方法は、テンプレートで指定することです。

std::tr1::bind<void(foo::*)(int)>(&foo::bar);

この方法は同じように明示的ですが、キャストよりも短くなります(static_castとにかく。ただし、同じ長さのCキャストよりもクリーンです。

于 2008-11-30T07:32:36.317 に答える
1

ジョンが示唆したように、これらのスニペットで発生する問題は次のとおりです。

  1. メンバー関数ポインターを渡すときは、その署名を指定する必要があります (オーバーロードされている場合)
  2. bind()値によって引数が渡されます。

最初の問題は、バインドに提供されたメンバー関数ポインターをキャストすることで解決されます。

    std::tr1::bind(static_cast< void(abc::*)(int) const >(&abc::hello), x, _1)(a);

2番目の問題は、呼び出し可能なオブジェクトをアドレスで渡すか(ジョンが提案したように)、TR1を使用して解決できます。reference_wrapper<>そうしないと、値で渡され、const-correctnessが幻覚を壊します。

与えられた xa 呼び出し可能オブジェクト:

std::tr1::bind( std::tr1::ref(x) , _1)(a);

bind()x constnessに従ってa適切に転送します。operator()

于 2008-11-22T10:07:03.323 に答える