简体   繁体   English

避免将左值引用绑定到临时数据容器和包装器的设计

[英]Design to avoid binding lvalue reference to temporary for data container and wrapper

I'm struggling with the design of a few (probably two) C++ classes that work together and implement sort of a data container (Vector) and a data wrapper (Integer) that wraps individual vector elements (or better to say the access to it).我正在努力设计几个(可能是两个)C++ 类,它们一起工作并实现某种数据容器(Vector)和一个包装单个矢量元素的数据包装器(Integer)(或者更好地说是对它的访问)。 The Vector simply holds a vector of int . Vector 仅包含一个int向量。 The Integer/wrapper provides access to an int (possibly without holding it). Integer/wrapper 提供对int的访问(可能不持有它)。

Requirements:要求:

  1. Wrapper/Integer must be available as lvalue Wrapper/Integer 必须作为左值可用
  2. The data container should hold the data as an vector of int (not as a vector of Integer)数据容器应将数据保存为int的向量(而不是 Integer 的向量)
  3. The wrapper also holds some other data members (no reinterpreting cast int -> Integer possible)包装器还包含一些其他数据成员(不能重新解释 cast int -> Integer 可能)

I fail to design this (see below) without running into the problem where an lvalue reference cannot bind to a temporary.我没有设计这个(见下文)而没有遇到左值引用不能绑定到临时的问题。 I understand that that's not possible and I understand that code is wrong (and why it's wrong).我知道这是不可能的,并且我理解代码是错误的(以及为什么它是错误的)。 There's no need to explain that lvalue references can't bind to rvalues.没有必要解释左值引用不能绑定到右值。 I'm struggling to find a solution to above requirements without this problem.我正在努力寻找没有这个问题的上述要求的解决方案。

How to design this in C++?如何在 C++ 中设计这个? (Can be any modern standard) (可以是任何现代标准)

#include<vector>
        
class Integer
{
  int& ref_t;
  bool other_data_member;

public:
  Integer(int& rhs): ref_t(rhs) {}

  Integer& operator=( int i )
  {
    ref_t = i;
    return *this;
  }
};



class Vector
{
  std::vector<int> data;

public:
  Vector(): data(10) {}
  
  Integer& operator[](int i)
  {
    return Integer( data[i] ); // caution: this doesn't work
  }
};



void write_one( Integer& i )
{
  i = 1;
}


int main()
{
  Vector v;
  write_one( v[5] );
}

Returning a “temporary” by value doesn't make a copy or even a move (guaranteed as of C++17, though often implemented as a conforming optimization in prior versions).按值返回“临时”不会进行复制甚至移动(从 C++17 开始保证,尽管在以前的版本中经常作为符合优化的方式实现)。 You have to do this, because your operator[] needs to form a new wrapper for whatever index.必须这样做,因为你的operator[]需要为任何索引形成一个的包装器。 (The reinterpret_cast approach has undefined behavior regardless of other members of Integer .) Generic code can bind auto&& to your proxy object because of lifetime extension , and can assign to it, so often need not be aware of the proxy (as is desirable). (无论Integer的其他成员如何, reinterpret_cast方法都具有未定义的行为。)由于生命周期延长,通用代码可以将auto&&绑定到您的代理 object ,并且可以分配给它,因此通常不需要知道代理(这是可取的)。

Separately, if you want to avoid copying arguments to functions like write_one that do know about the proxy type, you can accept const Integer& .另外,如果您想避免将 arguments 复制到像write_one这样知道代理类型的函数,您可以接受const Integer& To make that work, make your operator= const (which sounds weird until you remember that it's not the Integer that's being modified).为了使它工作,让你的operator= const (这听起来很奇怪,直到你记得它不是被修改的Integer )。

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

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