そのデータを所有せずに、いくつかのデータへの参照を保持する必要があるクラスがあります (つまり、実際のデータはスコープ外に出ないことが保証されています)。特に、クラスはコピーを作成できません。データのサイズは簡単に数ギガバイトになります。
さて、通常の実装(私が推測する)は、データへの参照を持つことです:
struct holder_ref {
type const& value;
holder_ref(type const& value) : value(value) { }
};
const
(問題には全く関係ありませんのでご注意ください)。
今、私は絶対にこのクラスを割り当て可能にする必要があります (つまり、作業中の を持っていoperator =
ます)。これはかなり一般的な問題だと思っていましたが、以前にどのように解決したかを思い出せません。
問題は、参照を割り当てることができず、これを回避する方法がないことです。私が思いついた唯一の解決策は、代入演算子の代わりに配置 new を使用することです。
// x = other_x; gets replaced with:
x.~T();
new (&x) T(other_x);
現在、これは機能し、標準に準拠しています。しかし、それは確かに醜いです。いいえ - 受け入れられません。
だから私は代替案を探しています。1 つのアイデアはポインターを使用することですが、コンストラクターが実際に動作することが保証されているかどうかはわかりません (また、従わなければならないインターフェイスのために、ポインターを渡すことは不可能です)。
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 であり、標準に準拠したソリューションが必要です。)