#include <iostream>

class ButtonObserver {
	public:
		inline constexpr ButtonObserver () : next (nullptr) {}
		friend class Button;

		virtual bool onClick (int x) = 0;
		virtual int onDoubleClick (short x, long y) = 0;
	private:
		ButtonObserver* next;
};

template <int Instance, typename Main>
class ButtonObserverRelay : public ButtonObserver {
	public:
		virtual bool onClick (int x) override {
			return static_cast<Main&> (*this).onButtonClick (x, this);
		}
		virtual int onDoubleClick (short x, long y) override {
			return static_cast<Main&> (*this).onButtonDoubleClick (x, y, this);
		}
};


class Button {
	public:
		constexpr Button () : firstObserver (nullptr) {}

		void addObserver (ButtonObserver* obs) {
			obs->next = firstObserver;
			firstObserver = obs;
		}
		bool onClick (int x) {
			// Beispiel: Iteriere solange die Observer bis einer "true" zurück gibt
			for (ButtonObserver* o = firstObserver; o; o = o->next) {
				if (o->onClick (x))
					return true;
			}
			return false;
		}
		int onDoubleClick (short x, long y) {
			// Beispiel: Summiere die Rückgabewerte der Observer
			int sum = 0;
			for (ButtonObserver* o = firstObserver; o; o = o->next) {
				sum += o->onDoubleClick (x, y);
			}
			return sum;

		}
	private:
		ButtonObserver* firstObserver;
};

class Screen : public ButtonObserverRelay<0, Screen>, public ButtonObserverRelay<1, Screen> {
	public:
		Screen () {
			btn0.addObserver (static_cast<ButtonObserverRelay<0, Screen>*> (this));
			btn1.addObserver (static_cast<ButtonObserverRelay<1, Screen>*> (this));
		}
		bool onButtonClick (int x, ButtonObserverRelay<0, Screen>*) {
			std::cout << "Button 0 Click(" << x << ")" << std::endl;
			return true;
		}
		int onButtonDoubleClick (short x, long y, ButtonObserverRelay<0, Screen>*) {
			std::cout << "Button 0 DoubleClick(" << x << ", " << y << ")" << std::endl;
			return 0;
		}
		bool onButtonClick (int x, ButtonObserverRelay<1, Screen>*) {
			std::cout << "Button 1 Click(" << x << ")" << std::endl;
			return true;
		}
		int onButtonDoubleClick (short x, long y, ButtonObserverRelay<1, Screen>*) {
			std::cout << "Button 1 DoubleClick(" << x << ", " << y << ")" << std::endl;
			return 0;
		}
		Button btn0, btn1;
};

int main () {
	Screen s;
	s.btn0.onClick (42);
	s.btn0.onDoubleClick (12, 3456);

	s.btn1.onClick (1);
	s.btn1.onDoubleClick (2, 3);
}