2

関数オブジェクトから状態を取得したい。ただし、関数オブジェクトはfunction<>テンプレートにキャストされています。どうすればいいですか?

つまり:

関数オブジェクト:

class Counter {
private:
    int counter_;
public:
    Counter():counter_(0) {cout << "Constructor() called" << endl;}
    Counter(int a):counter_(a) {cout << "Constructor(a) called" << endl;}

    void operator()(int sum) {
        cout << counter_++ + sum << endl;
    }

int getCounter() { return counter_;}
};

主に。私の最初のステップは、オブジェクトを直接使用することです。

int main() {
    Counter a(10);
    a(0);
    a(0);

    cout << "Counter: " << a.getCounter() << endl;

そのショー:

コンストラクタ(a)と呼ばれる

10

11

カウンター:12

それは大丈夫です、そしてそれは私が期待したものです。

しかし、

Counter b(10);
function<void(int)> f = b;
f(0);
f(0);
cout << "Counter: " << b.getCounter() << endl;

それが示している

コンストラクタ(a)と呼ばれる

10

11

カウンター:10

ああ!、fは実際のオブジェクトのラッパーだと思ったので、変更するfと実際に変更されbます。いいえ:fのコピーがありますがb、呼び出すことができません。f.getCounter()どのようにしてState(counter_ var)を取得できfますか?

Counter同じシグネチャ「void(int)」を持つ他の同様のクラスがいくつかあるため、(この例では)クラスを直接使用することはできません。また、呼び出し元の関数でそれらを不明瞭に使用したいと思います。

すべての関数オブジェクトに共通の基本クラスを使用してテンプレートを完全に回避することはできstd::functionますが、STLとテンプレートを使用したC++11のソリューションがもっとあると思います...

それで、その解決策はありますか?

ありがとう

4

2 に答える 2

3

参照ラッパーから関数を作成します。

function<void(int)> f = std::ref(b);

結果を与える:

Constructor(a) called
10
11
Counter: 12

もちろん、カウンターが破棄された後に関数が呼び出されないようにする必要があります。

関数オブジェクトからカウンターにアクセスする必要がある場合は、そのtargetメンバーを使用します。

if (Counter * c = f.target<Counter>()) {
    std::cout << "Counter: " << c->getCounter() << '\n';
} else {
    std::cout << "Not a counter.\n";
}
于 2012-06-22T13:12:19.253 に答える
2

これはキャストではありません:

function<void(int)> f = b;

Astd::functionは、関数オブジェクトのコピーをターゲットとして作成されます。

ターゲットを関数オブジェクトへの参照にすることができます。

function<void(int)> f = std::ref(b);

またはf、コピーを含めてから、そのコピーを次の場所から取得しますf

Counter* c = f.target<Counter>();
cout << "Counter: " << c->getCounter() << endl;

fの存続期間について心配する必要がないため、通常はコピーを含める方が安全ですb

于 2012-06-22T14:22:34.027 に答える