我正在编写一些时髦的音频代码,并试图使用运算符重载来创建一个非常简洁的API。它已成为一种C ++脑力激荡器......
我想要的东西会立即被“分配到索引”的复合运算符解决,我很确定它不存在。任何人都可能对以下是否可能有任何见解?
我有两种对象类型......
Frames frames; // audio data, contains 1 buffer (float *) for each channel
Sample s; // a single sample, 1 float for each channel
所以Sample
是帧的正交切片,即帧不是Sample
的数组。如果你知道音频,Frames
是“非交错的”,Sample
就是。
圣杯......
s = frames[1]; // statement 1. gets a copy of values in frame 1
frames[1] = s; // statement 2. replace values in frame 1 with those in Sample s
第一个没问题:
// in class Frames...
Sample& operator[](size_t idx) const {
Sample s;
s.left = _leftCh[idx];
s.right = _rightCh[idx];
return s;
}
但是第二个赋值是棘手的,因为上面的函数创建了数据的副本而不是引用。
我尝试使用引用定义Sample ...
class Sample {
public:
float& L;
float& R;
Sample(float& lt, float& rt) : L(lt), R(rt) {};
}
但是你不能做一些简单的事情......
Sample s(0.0, 0.0);
s.left = 0.2;
另一个可能的解决方案是让两个语句调用两个不同的运算符重载。然后强制执行该语句2调用this []重载,该重载返回一个指向值而不是Sample
对象的新Frames对象:
Frames& operator[](size_t idx) {
// Construct an new Frames object whose which
// points to value idx in each channel
Frames f(_size - idx);
f._leftCh = &_leftCh[idx];
f._rightCh = &_rightCh[idx];
return f;
}
然后将赋值运算符添加到Frames
,它只替换第一个值...
Frames& operator=(const Sample& s) {
_leftCh[0] = s.left;
_rightCh[0] = s.right;
return *this;
}
编译器通知我方法必须不仅仅是返回类型,但是通过在const
重载之一的方法名之后加operator[]
来解决这个问题。可能在这里有线索吗?有没有办法让声明1呼叫Sample& operator[]...
和声明2呼叫Frames& operator[]...
。或者有更好的方法来实现这个目标吗?
如果你已经做到这一点,感谢你的耐心等待!非常感谢...
答案 0 :(得分:5)
这个怎么样:
class SampleRef {
float &left_, &right_;
public:
SampleRef(float& left, float& right)
: left_(left), right_(right)
{}
operator Sample () {
return Sample(left_, right_);
}
SampleRef& operator= (const Sample &arg) {
left_ = arg.left;
right_ = arg.right;
return *this
}
};
SampleRef Frames::operator[] (size_t idx) {
return SampleRef(_leftCh[idx], _rightCh[idx]);
}
您当然也可以添加const
operator[]
重叠,这只会返回Sample
:
Sample Frames::operator[] (size_t idx) const {
return Sample(_leftCh[idx], _rightCh[idx]);
}
答案 1 :(得分:0)
你是否尝试过没有超载只是为了解决细节问题?例如sample = frame.getSample(); frame.setSample(sample);
一旦详细信息得到满足,您就可以添加语法糖并重载[]
和=
运算符。
看起来您想要维护对原始Sample的引用,例如:
sample.right = oldR;
sample.left = oldL;
f[x] = sample;
sample.right = newR;
sample.left = newL;
newSample = f[x];
assert(sample.right == newSample.right && sample.left == newSample.left);
这是对的吗?如果是这样,我认为你不能这样做,因为你“打破”你的样本将其插入到框架中,所以你失去了原来的连接。