3

我正在编写一些时髦的音频代码并尝试使用运算符重载来创建一个非常干净和简单的 API。它变得有点像 C++ 脑筋急转弯......

我想要的将通过“分配给索引”的复合运算符立即解决,我很确定它不存在。可能有人对以下是否可能有任何见解?

我有 2 种对象类型....

Frames frames;  // audio data, contains 1 buffer (float *) for each channel
Sample s;       // a single sample, 1 float for each channel

帧的正交切片也是如此Sample,即帧不是Sample's 的数组。如果您知道音频,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 调用这个 [] 重载,它返回一个指向值而不是对象的新 FramesSample对象:

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[]...。还是有更好的方法来实现这一点?

如果您已经做到了这一步,感谢您的耐心等待!非常感激...

4

2 回答 2

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]);
}
于 2013-03-22T09:24:08.197 回答
0

您是否尝试过不重载只是为了解决细节?例如sample = frame.getSample(); frame.setSample(sample);,一旦细节得到您的满意,您就可以添加语法糖并重载[]and=运算符。

看起来您想保留对原始样本的引用,例如:

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);

这个对吗?如果是这样,我认为您不能这样做,因为您“分解”了样本以将其插入框架中,因此您失去了原始连接。

于 2013-03-22T09:30:03.073 回答