C++ 从左值/右值上下文强制执行运算符版本

C++ 从左值/右值上下文强制执行运算符版本,c++,operator-overloading,lvalue,rvalue,C++,Operator Overloading,Lvalue,Rvalue,我正在尝试使用操作符重载为数组片的赋值创建一些好的语法。由于引用的常量正确性的一些特性,左值和右值切片需要不同的类。但是,我无法让编译器理解在给定上下文中使用哪个版本 下面的代码显示了原始代码的简化版本,虽然看起来有点做作,但它很好地解决了这个问题。在实际代码中,i是一组完整的索引,B/ConstB表示无法复制的巨大数组片段,从而激发了引用x 当我想在foo中完成作业时,就会出现问题。我希望右边的所有切片都产生一个ConstB对象,但是由于在这种情况下a1恰好是非const对象,所以使用了错误的

我正在尝试使用操作符重载为数组片的赋值创建一些好的语法。由于引用的常量正确性的一些特性,左值和右值切片需要不同的类。但是,我无法让编译器理解在给定上下文中使用哪个版本

下面的代码显示了原始代码的简化版本,虽然看起来有点做作,但它很好地解决了这个问题。在实际代码中,
i
是一组完整的索引,
B
/
ConstB
表示无法复制的巨大数组片段,从而激发了引用
x

当我想在
foo
中完成作业时,就会出现问题。我希望右边的所有切片都产生一个
ConstB
对象,但是由于在这种情况下
a1
恰好是非const对象,所以使用了错误的一个。我可以通过引入
const\u cast
来强制执行它,但我更喜欢不破坏用户代码的方式(即
foo
中的东西)。有没有一种方法可以强制分别为左值或右值调用给定的重载

守则:

struct B;
struct ConstB;

struct A
{
  double data[10];

  A() {}
  A&     operator=(const ConstB &b);
  ConstB operator()(int i) const;
  B      operator()(int i);
};


struct B
{
  double &x;

  B(double *d, int i);
  B& operator=(const A &a);
};

struct ConstB
{
  const double x;

  ConstB(const double *d, int i);
};



A& A::operator=(const ConstB &b) {
  data[0] = b.x;
  return *this;
}

ConstB A::operator()(int i) const {
  return ConstB(data,i);
}

B A::operator()(int i) {
  return B(data,i);
}


B::B(double *d, int i)
  : x(d[i]) {}

B& B::operator=(const A &a) {
  x=a.data[0];
  return *this;
}

ConstB::ConstB(const double *d, int i)
  : x(d[i]) {}



void foo(A &a1, A &a2, A&a3)
{
  a1(2) = a2;

  a3 = a1(3);
  // a3 = const_cast<const A&>(a1)(3);
}

int main(int argc, char *argv[])
{
  A a1;
  A a2;
  A a3;

  foo(a1,a2,a3);

  return 0;
}

为什么不为赋值运算符添加一个重载以获取a
B
?@NathanOliver,因为我希望保持
x
的常量正确性,在实际代码中,它是一个大向量。对于编译器优化来说,使用常量引用而不仅仅是引用似乎是一件好事。
test.cc: In function ‘void foo(A&, A&, A&)’:
test.cc:67:6: error: no match for ‘operator=’ (operand types are ‘A’ and ‘B’)
   a3 = a1(3);
      ^
test.cc:36:4: note: candidate: A& A::operator=(const ConstB&)
 A& A::operator=(const ConstB &b) {
    ^
test.cc:36:4: note:   no known conversion for argument 1 from ‘B’ to ‘const ConstB&’
test.cc:5:8: note: candidate: A& A::operator=(const A&)
 struct A
        ^
test.cc:5:8: note:   no known conversion for argument 1 from ‘B’ to ‘const A&’
test.cc:5:8: note: candidate: A& A::operator=(A&&)
test.cc:5:8: note:   no known conversion for argument 1 from ‘B’ to ‘A&&’