Это действительно о плохом представлении об обмене двумя ссылками. Ссылки не должны быть сброшены, поэтому они не должны быть возможными. Это я знаю.Способ обмена двумя ссылками в C++
Что я хочу сделать, это поменять местами две ссылки, таким образом, можно было бы поменять местами два указателя: адреса перепутаны но не данные. Предположим:
int a = 0, b = 1;
int *pA = &a, *pB = &b;
std::swap(pA, pB);
сейчас * УМ 1 и * рв 0, но по-прежнему 0 и Ь по-прежнему 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);
Теперь еще 0 и б еще 1, и ссылки внутри пА и РРК меняются местами. Жаль, что он не работает без довольно уродливого оператора =(). По крайней мере, это работает для меня в MSVC, не уверен, что g ++ примет его (но я думаю, что он должен).
Весь ссылочный своп предполагается использовать в объекте, который построен со ссылкой на другой объект внутри, и я хотел бы сделать функцию swap() на них. Я бы хотел избежать использования указателей из-за хорошей не-nullarity функции ссылок. Это также было бы более приятным дизайном (за исключением самого resetable_ref).
Есть ли у кого-нибудь лучшее представление о том, как это сделать? Может ли кто-нибудь подумать о некоторых проблемах с совместимостью/неопределенным поведением, с которыми можно столкнуться?
Я написал большую часть кода без компиляции, пожалуйста, несите меня, если вы заметили какую-либо опечатку.
EDIT: Мне кажется, что у многих людей отсутствует точка вопроса. Я знаю, как использовать указатели или даже как конвертировать указатели в хороший шаблон. Вопрос отмечен «взломать», и это то, что ожидается. Не говорите мне, как «не делайте этого, используйте указатель», поскольку это не то, что я спросил. Если вам не нравится эта тема, не отвечайте, но не уменьшайте вопрос только потому, что будете использовать указатель.
Я полагаю 'станд :: reference_wrapper' может работать. Тем не менее, он никогда не использовал его. – chris
Почему бы вам не использовать указатель, а не ссылку внутри вашего класса, сделать его конфиденциальным, а затем предоставить подходящие функции-члены, которые будут выступать в качестве аксессуаров к базовому 'int'? Таким образом, вы можете избежать всех неприятных проблем с reinterpret_cast/потенциально-неопределенным поведением. –
@chris спасибо, я понятия не имел, что существует –