public
Last active

When you want classes A and B to be mutually connected to each other, derive them from this class template.

  • Download Gist
MutuallyConnectable.h
C++
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
#pragma once
#ifndef __MutuallyConnectable_H__
#define __MutuallyConnectable_H__
 
// Usage: Suppose you want to have two classes A and B that are mutually connected to each other.
//
// Derive the class A from MutuallyConnectable<A, B> where A is the class you're deriving
// and B is the other class you want to make mutual connections with.
// Derive the class B from MutuallyConnectable<B, A>.
//
// Call MutuallyConnectable<A, B>::Connect(A, B) to create a connection.
// Call MutuallyConnectable<A, B>::Disconnect(A, B) to destroy a connection.
//
// Call A::GetConnected() to get a const reference to std::set<B *>.
// Call B::GetConnected() to get a const reference to std::set<A *>.
//
// If A or B is destroyed while it has non-zero connections, it will automatically remove the connections.
 
template <typename T, typename U> class MutuallyConnectable
{
private:
std::set<U *> m_Connected;
 
public:
// TODO: Change return type to `const decltype(m_Connected) &` or something
const std::set<U *> & GetConnected() const;
 
static void Connect(MutuallyConnectable<T, U> & MutuallyConnectable0, MutuallyConnectable<U, T> & MutuallyConnectable1);
static void Disconnect(MutuallyConnectable<T, U> & MutuallyConnectable0, MutuallyConnectable<U, T> & MutuallyConnectable1);
 
protected:
MutuallyConnectable();
virtual ~MutuallyConnectable();
 
private:
MutuallyConnectable(const MutuallyConnectable<T, U> &) = delete;
MutuallyConnectable<T, U> & operator = (const MutuallyConnectable<T, U> &) = delete;
 
void ConnectWithoutReciprocating(MutuallyConnectable<U, T> & MutuallyConnectable);
void DisconnectWithoutReciprocating(MutuallyConnectable<U, T> & MutuallyConnectable);
 
friend class MutuallyConnectable<U, T>;
};
 
#include "MutuallyConnectable.hpp"
 
#endif // __MutuallyConnectable_H__
MutuallyConnectable.hpp
C++
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
template <typename T, typename U> MutuallyConnectable<T, U>::MutuallyConnectable()
{
}
 
template <typename T, typename U> MutuallyConnectable<T, U>::~MutuallyConnectable()
{
for (auto & Connected : m_Connected)
{
static_cast<MutuallyConnectable<U, T> *>(Connected)->DisconnectWithoutReciprocating(*this);
}
}
 
template <typename T, typename U> const std::set<U *> & MutuallyConnectable<T, U>::GetConnected() const
{
return m_Connected;
}
 
template <typename T, typename U> void MutuallyConnectable<T, U>::Connect(MutuallyConnectable<T, U> & MutuallyConnectable0, MutuallyConnectable<U, T> & MutuallyConnectable1)
{
MutuallyConnectable0.ConnectWithoutReciprocating(MutuallyConnectable1);
MutuallyConnectable1.ConnectWithoutReciprocating(MutuallyConnectable0);
}
 
template <typename T, typename U> void MutuallyConnectable<T, U>::Disconnect(MutuallyConnectable<T, U> & MutuallyConnectable0, MutuallyConnectable<U, T> & MutuallyConnectable1)
{
MutuallyConnectable0.DisconnectWithoutReciprocating(MutuallyConnectable1);
MutuallyConnectable1.DisconnectWithoutReciprocating(MutuallyConnectable0);
}
 
template <typename T, typename U> void MutuallyConnectable<T, U>::ConnectWithoutReciprocating(MutuallyConnectable<U, T> & MutuallyConnectable)
{
m_Connected.insert(static_cast<U *>(&MutuallyConnectable));
}
 
template <typename T, typename U> void MutuallyConnectable<T, U>::DisconnectWithoutReciprocating(MutuallyConnectable<U, T> & MutuallyConnectable)
{
m_Connected.erase(static_cast<U *>(&MutuallyConnectable));
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.