C ++ 11;非静态数据成员初始化是否可以访问其他数据成员?

时间:2012-04-26 12:47:43

标签: c++ gcc lambda c++11 mingw

我非常喜欢C#中属性的概念,作为一个小小的项目,我一直在修改用C ++实现它们的想法。我遇到了这个看似相当不错的示例https://stackoverflow.com/a/5924594/245869,但我忍不住认为lambdas和非静态数据成员初始化可以使用这个想法使用一些非常好的语法。这是我的实施:

#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_'

所以看起来我的属性实现的概念是有效的,但它可能是徒劳的,因为我无法从我的lambda函数访问其他数据成员。我不确定标准是如何定义我在这里要做的,我完全没有运气,或者我只是不在这里做某事?

1 个答案:

答案 0 :(得分:2)

您的属性是包含对象(property<int>的实例)的不同对象(Foobar的实例)。因此,其成员函数传递的是不同的this,而不是您需要访问的num_ - 因此您不能这样做。如果lambdas是在Foobar的非静态成员函数中定义的,那么他们就会捕获该函数的this参数,并且可以访问封闭对象的成员(显式为this->num_ )。但lambda是在类中定义的,其中非静态数据成员实际上并不存在。如果lambdas 可以访问num_ num_Foobar的实例是哪个?

我看到的最简单的解决方案是属性存储指向封闭对象的指针。这样,它可以自由访问其非静态成员。缺点是声明稍微复杂一些(你必须做property<int, Foobar> num)并且你需要通过传递this指针来初始化属性。所以你将无法在类中完成它,它必须在构造函数的初始化列表中,因此否定了C ++ 11的数据成员初始化的优势。

此时,this可用于lambdas无论如何都可以捕获(通过值,而不是通过引用!)因此,如果将属性的初始化移动到Foobar,那么您的代码实际上将以最小的更改工作。构造(多个):

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

有没有人知道传递给碰巧调用的任何构造函数的this是否可用于类定义中的非静态成员初始化?我怀疑它不是,但如果是的话,同样的结构将在类定义中起作用。