template <class T> T& Vector<T>::Set(int i, T&& x) { ASSERT(i >= 0); const int count = GetCount(); if (i == count) return Add(pick(x)); else if (i > count) { At(i - 1); return Add(pick(x)); } T* addr = vector + i; addr->~T(); ::new(addr) T(pick(x)); return *addr; }
template <class T> T& Vector<T>::Set(int i, T&& x) { ASSERT(i >= 0); At(i); T* addr = vector + i; addr->~T(); ::new(addr) T(pick(x)); return *addr; }
I am considering this, but single element Set was always just v.At(i) = pick(src);
mirek wrote on Sun, 28 January 2018 16:47I am considering this, but single element Set was always just v.At(i) = pick(src);
Well, yes. This will work as well. But this is significantly less intuitive. Your way of solving this problem definitely didn't come to my mind when I was looking for a solution. Adding of an rvalue-based version of Set definitely won't break API because you already have a reference-based version. This is just another performance optimization.
My solution is based on move-constructor and yours is based on move-operator.
const T& Vector::Get(int i, const T& default) { return i >= 0 && i < GetCount() ? Get(i) : default; }
void Vector::Set(int i, T&& x) { At(i) = pick(x); }
Do you see any problem with trivial implementation
void Vector::Set(int i, T&& x) { At(i) = pick(x); }
T& Vector::Set(int i, T&& x) { return At(i) = pick(x); }
T& v = vector.At(ind) = T(args);