单独的处理程序lvalue和rvalue []运算符

时间:2018-03-14 20:36:55

标签: c++ operator-overloading

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

示例代码:

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] called\n", idx);
  return a;
}

unsigned & test::operator [](unsigned const idx) {
  printf("non-const [%u] called\n", idx);
  return a;
}

int main() {
  test t;
  unsigned a;
  a = 0;
  printf("a = %u\n", a);
  t[0] = a;
  printf("stored a to t[0]; a = %u\n", a);
  a = t[0];
  printf("read a from t[0]; a = %u\n", a);
}

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

请不要将此标记为C++ Operator Overloading [ ] for lvalue and rvalue的副本,因为此问题不一样,即使它看起来类似。

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

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] called\n", idx);
  return a;
}

/*unsigned & test::operator [](unsigned const idx) {
  printf("non-const [%u] called\n", idx);
  return a;
}*/

int main() {
  test t;
  unsigned a;
  a = t[0];
  printf("read a from t[0]; a = %u\n", a);
}

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

1 个答案:

答案 0 :(得分:1)

不,是的。

不,上下文不能改变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 idxpr_unsigned,并在将元素分配到/来自test时运行任意代码。