6

私はC#でのプロパティのアイデアが本当に好きで、ちょっとした副次的なプロジェクトとして、C++でプロパティを実装するというアイデアをいじくり回してきました。私はこの例https://stackoverflow.com/a/5924594/245869に出くわしましたが、これはかなりいいようですが、ラムダと非静的データメンバーの初期化によって非常に良い構文を使用できるようになるかもしれないと思わずにはいられませんでしたこのアイデアで。これが私の実装です:

#include <iostream>
#include <functional>

using namespace std;


template< typename T >
class property {

public:
    property(function<const T&(void)> getter, function<void(const T&)> setter)
        : getter_(getter),
          setter_(setter)
    {};

    operator const T&() {
        return getter_();
    };

    property<T>& operator=(const T& value) {
        setter_(value);
    }

private:
    function<const T&(void)> getter_;
    function<void(const T&)> setter_;

};


class Foobar {

public:
    property<int> num {
        [&]() { return num_; },
        [&](const int& value) { num_ = value; }
    };

private:
    int num_;

};


int main() {
    // This version works fine...
    int myNum;
    property<int> num = property<int>(
        [&]() { return myNum; },
        [&](const int& value) { myNum = value; }
    );
    num = 5;

    cout << num << endl;  // Outputs 5
    cout << myNum << endl;  // Outputs 5 again.

    // This is what I would like to see work, if the property
    // member of Foobar would compile...
    // Foobar foo;
    // foo.num = 5;

    // cout << foo.num << endl;

    return 0;
}

プロパティクラスは通常どおり使用できますが[main()の例を参照]、g ++ 4.7を使用するMinGWは、プロパティをデータメンバーとして使用する試みを特に気にしません。

\property.cpp: In lambda function:
\property.cpp:40:7: error: invalid use of non-static data member 'Foobar::num_'

したがって、プロパティ実装の概念は機能しているように見えますが、ラムダ関数から他のデータメンバーにアクセスできないため、無駄になる可能性があります。規格が私がここでやろうとしていることをどのように定義しているかわかりません、私は完全に運が悪いのですか、それとも私はここで何かをしていないだけですか?

4

1 に答える 1

3

プロパティは、property<int>含まれているオブジェクト(のインスタンス)とは異なるオブジェクト(のインスタンスFoobar)です。そのため、そのメンバー関数は、thisアクセスする必要のある関数ではなく、別の関数に渡されますnum_。そのため、そのように行うことはできません。ラムダがの非静的メンバー関数で定義されている場合、ラムダはFoobarその関数の引数をキャプチャthisし、囲んでいるオブジェクトのメンバーにアクセスできます(明示的にとしてthis->num_)。ただし、ラムダはクラスで定義されており、非静的データメンバーは実際には存在しません。ラムダにアクセスできるとしたらnum_num_どのインスタンスのどのインスタンスがFoobarそれでしたか?

私が見る最も簡単な解決策は、プロパティがそれを囲むオブジェクトへのポインタを格納することです。そうすれば、非静的メンバーに自由にアクセスできます。欠点は、宣言が少し複雑になり(実行する必要があります)、ポインターproperty<int, Foobar> numを渡してプロパティを初期化する必要があることです。thisしたがって、クラスでそれを行うことはできません。コンストラクターの初期化リストに含まれている必要があるため、C++11のデータメンバーの初期化の利点が無効になります。

その時点でthis、ラムダはとにかく(参照ではなく値で!)キャプチャできるので、プロパティの初期化をFoobarのコンストラクターに移動した場合、コードは実際には最小限の変更で機能します。

Foobar::Foobar():
    num {
        [this]() { return this->num_; },
        [this](const int& value) { this->num_ = value; }
    }
{
}

this呼び出されたコンストラクターに渡されたものが、クラス定義の非静的メンバーの初期化に使用できるかどうかを誰かが知っていますか?そうではないと思いますが、そうである場合は、クラス定義内で同じ構造が機能します。

于 2012-04-26T14:42:12.933 に答える