Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/142.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;使用转换重载[]_C++_Overloading - Fatal编程技术网

C++ C++;使用转换重载[]

C++ C++;使用转换重载[],c++,overloading,C++,Overloading,我有一个表示布尔值向量的C数据结构;出于我无法控制的原因,布尔值在内部存储为整数,有两个神奇的值(不是0和1…)表示真和假。我创建了一个C++类来封装这个C结构,它工作得很好。我已经实现了set()和get()方法,如下所示: void Class::set(size_t index , bool value) { if (value) c_ptr[index] = SPECIAL_TRUE_VALUE; else c_ptr[index] =

我有一个表示布尔值向量的C数据结构;出于我无法控制的原因,布尔值在内部存储为整数,有两个神奇的值(不是0和1…)表示真和假。我创建了一个C++类来封装这个C结构,它工作得很好。我已经实现了
set()
get()
方法,如下所示:

void Class::set(size_t index , bool value) {
     if (value)
        c_ptr[index] = SPECIAL_TRUE_VALUE;
     else
        c_ptr[index] = SPECIAL_FALSE_VALUE;
}
这工作正常;但理想情况下,我希望重载运算符[],但是我不清楚如何/是否可以做到这一点-由于bool和整数值之间的特殊转换

struct pseudo_reference {
  operator bool()const&&{
    return c->get(index);
  }
  pseudo_reference operator=(bool b)&&{
    c->set(index, b);
    return {c,index};
  }

  // sometimes having named functions is useful:
  bool get() const&& {
    return std::move(*this);
  }
  void set(bool b)&& {
    std::move(*this) = b;
  }
  pseudo_reference()=delete;
private:
  Class* c;
  size_t index;
  pseudo_reference(pseudo_reference&&o)=default; // not exposed
  pseudo_reference(Class* pc, size_t i):c(pc),index(i){}
  friend class Class;
};
类中

pseudo_reference operator[](size_t i){
  return {this, i};
}
bool operator[](size_t i)const{
  return c_ptr[index] == SPECIAL_TRUE_VALUE;
}
我存储了一个指针和一个索引,因此避免了在我的
伪参考
中重新实现
get
/
set
的逻辑。这种
伪_引用可能是短期的,因此大小优化可能并不重要

我阻止了所有非右值操作,以阻止存储
伪\u引用
。您可以相对无害地使所述操作不受右值限制,但根据我的经验,
pseudo_references
是行为类似于引用的值,因此如果它们不持久就更好了


有人仍然可以通过
auto&&x=c[33]存储
pseudo_引用,但如果不移动它,就无法使用它。希望它能抓住最容易出错的用法<代码>自动x=c[33]无效。

您可以返回一个包装器帮助器类,该类为您处理分配

struct WrapMe {
    c_ptr_T &value;
    WrapMe(c_ptr_T &_value) : value(_value) {}
    // handles assignment of bool values
    WrapMe & operator=(const bool b) {
       value = (b) ? SPECIAL_TRUE_VALUE : SPECIAL_FALSE_VALUE;
       return *this;
    }
    // handles cast to bool
    operator bool() const { return value == SPECIAL_TRUE_VALUE; }
};

class Class {
   WrapMe operator[](const int idx) { return WrapMe(c_ptr[idx]); }
   // ...
};

要实现
操作符[]()
,您需要返回一个代理对象,当它出现在
=
的左侧时,该代理对象执行实际赋值:

struct proxy {
    proxy& operator=( bool value ) {
        c_.c_ptr[ index_ ] = value ? SPECIAL_TRUE_VALUE : SPECIAL_FALSE_VALUE;
        return *this;
    }
    operator bool() const { // for when it's just used normally, not =
        return c_ptr[ index ] == SPECIAL_TRUE_VALUE;
    }
private:
    Class &c_;
    size_t const index_;
    proxy( Class &c, size_t index ) : c_( c ), index_( index ) { }
    friend class Class;
}

class Class {
public:
    proxy operator[]( size_t index ) {
        return proxy( *this, index );
    }
    bool operator[]( size_t index ) const { // read-only access is easy
        return c_ptr[ index ] == SPECIAL_TRUE_VALUE;
    }
    // ...
};

或者类似的东西。

您需要阅读一些关于代理类的内容是的——我今天已经了解了代理类——以及重载赋值运算符;这对于你的解决方案来说可能是可行的,也可能是不可行的,但是你应该考虑转换的频率和布尔访问的频率。如果您主要使用set/get/[]函数,而很少使用特殊的_*_值转换,则只存储布尔值,然后仅在需要时进行转换可能会更容易。为了响应@user1978011的编辑尝试,我特意将其设置为私有。
friend类
应该允许
class
构造
pseudo\u引用
s。好吧-我想我了解它是如何工作的?您将为对
set()
方法的每次访问实例化一个伪\u引用?这看起来确实有点重?@user422005它是一个指针(指向
)和一个
大小
。那重物怎么这么重?引用通常是作为指针实现的(如果不是内联的,则不存在),因此我们只讨论返回数据引用的几个字节。一个称职的编译器可以将其内联到不存在的状态,因为它的寿命只够在指针上调用
set
get
。对
get
set
的原始调用进行优化分析,如果有很大差异,我会感到震惊。立即消失的小堆栈对象很便宜。@Yakk,你能用
bool操作符[](size\t i)const
来代替
operator bool()const
?这样,只要处理右值访问,就可以将代理转换为
bool
。我记得在通过代理读取时看到过这种转换,但我想再次检查。@vsoftco a
const\u proxy
proxy
通常是不同的类型(它不仅仅是
const proxy
——有点像指针,
const指针
不同于
指向const
的指针)。我让
[]const
直接返回值,而不是编写一个只调用
get
deferred的奇特类。看起来更简单,不是吗?