У меня есть класс, который должен содержать ссылку на некоторые данные, не имея этих данных (то есть фактические данные гарантированно не выйдут за рамки). В частности, , класс не может сделать копию - размер данных составляет несколько гигабайт.
Теперь обычная реализация (я полагаю) должна иметь ссылку на данные:
struct holder_ref {
type const& value;
holder_ref(type const& value) : value(value) { }
};
(Обратите внимание, что const
ness не имеет абсолютно никакого отношения к проблеме).
Теперь мне совершенно необходимо, чтобы этот класс был назначаемым (т.е.есть рабочий operator =
).Я думал, что это довольно распространенная проблема, но я не могу вспомнить, как (если вообще) я решил ее раньше.
Проблема в том, что ссылка не может быть назначена , и простоникак не обойтись.Единственное решение, которое я придумал, использует новое размещение вместо оператора присваивания:
// x = other_x; gets replaced with:
x.~T();
new (&x) T(other_x);
Теперь это работает и соответствует стандарту.Но это точно уродливо.Нет - недопустимо.
Поэтому я ищу альтернативы.Одна идея состоит в том, чтобы использовать указатели, но я не уверен, гарантированно ли работает мой конструктор (и передать указатель невозможно из-за интерфейса, которому я должен придерживаться):
struct holder_ptr {
type const* value;
// Is this legal?
holder_ptr(type const& value = 0) : value(&value) { }
};
Но я 'Я бы предпочел использовать ссылку, если это вообще возможно.Только - как реализовать оператор присваивания?
struct holder_ref {
type const& value;
holder_ref(type const& value = 0) : value(value) { }
holder_ref& operator =(holder_ref const& other) {
// Now what?!
return *this;
}
};
В качестве контрольного примера рассмотрим следующий код:
int main() {
int const TEST1 = 23;
int const TEST2 = 13;
int const TEST3 = 42;
std::vector<holder_ptr> hptr(1);
std::vector<holder_ref> href(2);
// Variant 1. Pointer.
hptr[0] = holder_ptr(TEST1);
// Variant 2. Placement new.
href[0].~holder_ref();
new (&href[0]) holder_ref(TEST2);
// Variant 3. ???
href[1] = holder_ref(TEST3);
assert(*hptr[0].value == TEST1); // Works (?)
assert(href[0].value == TEST2); // Works
assert(href[1].value == TEST3); // BOOM!
}
(Кроме того, просто чтобы прояснить это - тип мы 'речь идет не о POD, и мне нужно стандартное совместимое решение.)