返回包装类中赋值运算符的类型
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
。换句话说,分配之后的CCD_ 8。如果您通过引用返回,a3::i_ == 1
。
相关文章:
- 标准库类型的赋值运算符的引用限定符
- 如果类在 C++ 中具有常量或引用类型的非静态数据成员,为什么编译器不提供默认赋值运算符?
- C++不同类型的默认赋值运算符
- 为什么类的赋值运算符的返回类型通常是非常量(而不是常量)引用?
- 具有临时对象的 Fundamenta 数据类型赋值运算符
- 引用模板类型的赋值运算符需要非常量重载
- 带有非类型参数的C++模板类:如何重载赋值运算符
- 重载全常量类型的复制赋值运算符的正确方法是什么?
- 重载非类型模板结构的成员结构的复制赋值运算符
- 表达式模板的核心功能:赋值运算符子模板类型
- 如何重载赋值运算符以允许我的类等于基元类型,例如'int'
- 返回赋值运算符的类型
- 在 Angelscript 中为 glm::vec3 的基于 vic3 的值类型注册赋值运算符
- 如果类类型是按值调用的函数的参数,则会调用该类的重载赋值运算符吗?
- 返回 C++ 中重载赋值运算符的类型
- 为什么引用类型成员会导致删除隐式声明的复制赋值运算符
- 复合赋值运算符的类型/类型转换?(例如*=(星形等于))
- 重载赋值运算符:不同的数据类型-不可能
- C++11:赋值运算符是否阻止一个类型成为POD,从而全局初始化
- 从"int"到非标量类型赋值运算符的转换 - 对象到 int