繁体   English   中英

包装类中赋值运算符的返回类型?

[英]Return type of assignment operators in wrapper class?

我想出了以下代码来在C ++中实现C#样式的属性。 它基本上是围绕typename T的包装器类,带有用户定义的get / set函数:

#include <functional>

template <typename T>
struct property
{
    property(std::function<T(void)> getter, std::function<void(const T&)> setter)
        : get(getter), set(setter) { }

    property(std::function<T(void)> _getter)
        : get(_getter), set([](const T&) { throw std::exception(); }) { }

    property<T>& operator=(const T& value) { set(value); return *this; } // w i h   o   s   h r ? 
    T operator=(const T& value) { set(value); return get(); }            //  h c   t   u e   e e   
    operator T() { return get(); }

    property<T>& operator=(property<T>& value) { set(value); return *this; };   //...
    T operator=(property<T>& value) { set(value); return get(); };              //...

    property<T>& operator=(property<T>&) = delete;

    // arithmetic / assignment
#define OP(__OP__) \
    T operator __OP__(const T& rhs) { return get() __OP__ rhs; } \
    T operator __OP__##= (const T& rhs) { set(get() __OP__ rhs); return get(); }              //...
    //property<T>& operator __OP__##= (const T& rhs) { set(get() __OP__ rhs); return *this; } //...
    OP(+); OP(-); OP(*); OP(/); OP(%); OP(^); OP(&); OP(|);
#undef OP

    // bit shift
#define OP(__OP__) \
    T operator __OP__(int rhs) { return get() __OP__ rhs; } \
    property<T>& operator __OP__##= (int rhs) { set(get() __OP__ rhs); return *this; }
    OP(<<); OP(>>);
#undef OP

    // comparison / logic
#define OP(__OP__) bool operator __OP__(const T& rhs) { return get() __OP__ rhs;}
    OP(<); OP(>); OP(==); OP(!=); OP(<=); OP(>=); OP(&&); OP(||);
#undef OP

    // inc/dec
#define OP(__OP__) \
    property<T>& operator __OP__##__OP__() { set(get() __OP__ 1); return *this; } \
    T operator __OP__##__OP__(int) { T value = get(); operator __OP__##__OP__(); return value; }
    OP(+); OP(-);
#undef OP

    T operator ~() { return ~get(); }
    bool operator !() { return !get(); }

private:
    std::function<T(void)> get;
    std::function<void(const T&)> set;
};

struct test
{ 
    property<int> a = property<int>([&]()
    {
        return x/10;
    }, 
    [&](int value) 
    {
        x = value*10;
    });

    property<int> b = property<int>([&]()
    {
        return y+10;
    }, 
    [&](int value) 
    {
        y = value-10;
    });

private:
    int x, y;
};

using namespace std;
void main()
{
    test x;

    x.a = 5;
    x.a = x.a + 15;
    x.a *= 5;
    x.b = x.a;
    x.b += x.a / 10;

    cout << "property a=" << dec << x.a << endl; // should be 100
    cout << "property b=" << dec << x.b << endl; // should be 110
}

我的主要问题是,赋值运算符应返回T还是property<T>& 返回引用似乎更好,但是我想避免意外重新分配整个类(包括get / set函数),尽管我认为重载operator=(property<T>&)并删除复制构造函数足以防止这种情况。
无论如何,两者似乎产生相同的结果,所以两者之间有什么区别吗? 您想要哪个,为什么?

编辑相关问题:如果未定义set函数,是否有某种方法可以在编译时检测赋值,而不是抛出运行时异常?

在大多数情况下,按副本返回可以正常工作,但在某些不正常的情况下则不行。 考虑以下:

struct A { 
  A(int i) : i_{i} {} 
  int i_; 

  A operator=(A const& A) { i_ = a.i_; return *this; }
};

然后尝试:

A a1{1};
A a2{2};
A a3{3};
(a3 = a2) = a1; // What is the value of a3::i_?

通过复制返回意味着a3 = a2分配生成一个临时,该临时被重新分配为等于a1 换句话说,赋值后a3::i_ == 2 如果通过引用返回,则a3::i_ == 1

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM