1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
   | #include <cstring>
#include <algorithm>
 
template< class T >
class SwappableReference 
{
public:
	T & ref;
	operator T& () const
	{
		return ref;
	}
	SwappableReference(T & r) : ref(r) {}
 
	void Swap(SwappableReference< T > & other)
	{
		//Cette fonction contourne la constance de la référence
		//En manipulant directement les données binaires.
		//C'est un peu comme un const_cast bien gras...
		const size_t mySize = sizeof *this;
		char bytes[ mySize ];
		std::memcpy(bytes, &other, mySize);
		std::memcpy(&other, this, mySize);
		std::memcpy(this, bytes, mySize);
	}
private:
	//On interdit quand même l'assignation:
	//Seuls la copie et le swap sont autorisés
	SwappableReference<T> & operator=(SwappableReference<T> const &);
};
 
namespace std
{
	//NOTE: La spécialisation partielle de fonction n'étant pas permise,
	//ce code ajoute une surcharge de std::swap() au lieu d'ajouter une spécialisation de template.
	//Ce n'est pas vraiment autorisé, mais il n'existe pour l'instant pas d'autre moyen.
	template< class T >
	void swap(SwappableReference< T > & left, SwappableReference< T > & right)
	{
		left.Swap(right);
	}
}
 
//--- Utilisation ---
 
class A
{
public:
	A(const int & P_i) : m_ri(P_i) {}
 
	SwappableReference<const int> m_ri;
 
	//Opérateur = redéfini avec fonction swap
	//NOTE: L'opérateur prend son paramètre par valeur et non par référence:
	//C'est pour forcer un appel au constructeur de copie.
	A & operator=(A tmp)
	{
		Swap(tmp);
		return *this;
	}
 
	void Swap(A & other)
	{
		//NOTE: On peut aussi utiliser notre surcharge de std::swap,
		//mais je préfère éviter...
		m_ri.Swap(other.m_ri);
	}
 
};
 
namespace std
{
	template<> void swap<A>(A & left, A & right) { left.Swap(right); }
}
 
//--- Test ---
#include <vector>
#include <iostream>
 
void TestReference(void)
{
	int L_i(0);
	A a(L_i);
 
	std::vector<A> L_vect;
	L_vect.push_back(a);
 
	int const & ri = L_vect[0].m_ri;
	L_i = 42;
 
	std::cout << ri << std::endl;
} |