これは、2 つの参照を交換するという悪い考えに関するものです。参照はリセット可能であると想定されていないため、可能であるとは想定されていません。私が知っているのはそれだけです。
私がやりたいのは、2つのポインタを交換する方法で、2つの参照を交換することです:アドレスは交換されますが、データは交換されません。推定:
int a = 0, b = 1;
int *pA = &a, *pB = &b;
std::swap(pA, pB);
現在、*pA は 1 で *pB は 0 ですが、a はまだ 0 で、b はまだ 1 です。ただし、これは参照では不可能です。
int a = 0, b = 1;
int &rA = a, &rB = b;
std::swap(pA, pB);
現在、参照は交換されていますが、元の値も交換されています。私が考えることができる唯一のことはこれです:
template <class _Ty>
struct resetable_ref {
_Ty &ref;
inline resetable_ref(resetable_ref &r)
:ref(r.ref)
{}
inline resetable_ref(_Ty &_ref)
:ref(_ref)
{}
inline resetable_ref &operator =(resetable_ref &r)
{
if(sizeof(resetable_ref) == sizeof(void*)) // compile-time constant (true)
*reinterpret_cast<void**>(this) = *reinterpret_cast<void**>(&r);
else
memcpy(this, &r, sizeof(resetable_ref)); // optimized away as dead code
return *this;
}
inline operator _Ty &()
{
return ref;
}
};
int a = 0, b = 1;
resetable_ref<int> rrA(a), rrB(b);
std::swap(rrA, rrB);
ここで、a は 0 のままで、b は 1 のままで、rrA と rrB 内の参照が交換されます。やや醜い演算子 =() なしでは機能しないのは残念です。少なくとも MSVC で動作しますが、g++ がそれを受け入れるかどうかはわかりません (しかし、そうすべきだと思います)。
参照スワップ全体は、内部の別のオブジェクトへの参照で構築されたオブジェクトで使用されることになっています。それらに swap() 関数を作成したいと思います。参照の素晴らしい非nullarity機能のために、ポインターの使用を避けたいと思います。また、より優れた設計になります (resetable_ref 自体を除く)。
誰かがそれをどうやって進めるかについてより良い考えを持っていますか? これで遭遇する可能性のある互換性/未定義の動作の問題を考えられる人はいますか?
私はほとんどのコードをコンパイルせずに書きました。タイプミスに気付いた場合はご容赦ください。
編集:多くの人が質問の要点を見逃しているようです。ポインターの使い方、またはポインターを素敵なテンプレートにラップする方法さえ知っています。質問には「ハック」というタグが付けられており、それが予想されることです。それは私が尋ねたことではないので、「やらないで、ポインタを使って」のようなことを言わないでください。トピックが気に入らない場合は、回答しないでください。ただし、ポインターを使用するという理由だけで質問に反対票を投じないでください。