单独的处理程序左值和右值 [] 运算符

separate handlers lvalue and rvalue [] operators

本文关键字:运算符 单独 处理 程序      更新时间:2023-10-16

有没有办法使 [] 运算符在左值和右值上下文中以不同的方式处理?

示例代码:

include <stdio.h>
class test {
public:
unsigned a;
unsigned const & operator [](unsigned const idx) const;
unsigned & operator [](unsigned const idx);
};
unsigned const & test::operator [](unsigned const idx) const {
printf("const [%u] calledn", idx);
return a;
}
unsigned & test::operator [](unsigned const idx) {
printf("non-const [%u] calledn", idx);
return a;
}
int main() {
test t;
unsigned a;
a = 0;
printf("a = %un", a);
t[0] = a;
printf("stored a to t[0]; a = %un", a);
a = t[0];
printf("read a from t[0]; a = %un", a);
}

t[0] = a;具有 lvalue-context [] 运算符,a = t[0];具有 rvalue-context [] 运算符,但它们都是通过 non-const 函数处理的。我也试图声明unsigned const & test::operator [](unsigned const idx)方法,但它没有编译并说不允许这种重载。有没有办法(我需要它)通过不同的处理程序处理 [] 运算符t[0]=a;a=t[0];

请不要将其标记为左值和右值的C++运算符重载 [ ] 的副本,因为这个问题并不相同,即使它看起来相似。

添加了可能也相关的简化代码: 包括

class test {
public:
unsigned a;
unsigned const & operator [](unsigned const idx) const;
/*unsigned & operator [](unsigned const idx);*/
};
unsigned const & test::operator [](unsigned const idx) const {
printf("const [%u] calledn", idx);
return a;
}
/*unsigned & test::operator [](unsigned const idx) {
printf("non-const [%u] calledn", idx);
return a;
}*/
int main() {
test t;
unsigned a;
a = t[0];
printf("read a from t[0]; a = %un", a);
}

我注释掉了非常量运算符 [],删除了对 t[0] 的写入,现在它编译并使用 [] 所需的方法。但是一旦我取消注释非常量,它就会开始使用它并忽略前一个。换句话说,问题是:有没有办法在所有可能的地方使 const 优于非 const ?

否,是。

否,上下文不能更改运算符或函数在C++的返回类型。

是的,您可以使用伪引用来伪造它。

伪引用是重载operator =(T const&)&&operator T()&&的对象。

struct pr_unsigned { // lazy name, do better
unsigned* target;
void operator=(unsigned const& in)&&{ *target=in; }
operator unsigned()&&{ return *target; }
pr_unsigned(pr_unsigned&&)=delete;
};

这有点像玩具,但是:

pr_unsigned test::operator [](unsigned const idx) { return {&a}; }

我们现在有不同的代码路径用于test[2]=3;foo=test[0];

这远非完美的模拟;auto x = test[2];做错了事。 但这并不可怕。

您可以将test*unsigned idx存储在pr_unsigned中,并在将元素分配给/从元素时test上运行任意代码。