<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Beobachterliste zur Kompilierzeit ( Template-Meta Programming )]]></title><description><![CDATA[<p>Hallo C++ Forum,<br />
für ein momentanes Projekt habe ich angefangen ein Beobachter System zu schreiben, welches den Vorteil hat, dass man die einzelnen Beobachter nicht zur Laufzeit bei den Subjekten anmelden muss. Die Namen in dem Beispiel sind extra so gewählt, dass alles verständlich sein sollte ( normalerweise würde ich natürlich T, U, Ts, Us etc als Parameter verwenden ). Soweit scheint alles zu funktionieren und wollte einfach mal ein wenig Feedback zur Art und Weise der Lösung bekommen <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f603.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--grinning_face_with_big_eyes"
      title=":D"
      alt="😃"
    /></p>
<pre><code>class SubjectOne {};
class SubjectTwo {};
class SubjectThree {};

template &lt; typename... TSubjects &gt;
class Observer
{
public:
	using SubjectList = std::tuple&lt;TSubjects...&gt;;
};

using ObserverOne = Observer&lt;SubjectOne, SubjectTwo&gt;;
using ObserverTwo = Observer&lt;SubjectTwo, SubjectThree&gt;;

using ObserverList = std::tuple&lt;ObserverOne, ObserverTwo&gt;;
using SubjectList  = std::tuple&lt;SubjectOne, SubjectTwo, SubjectThree&gt;;

template &lt; typename TObserverList, typename TSubjectList &gt;
class SubjectManager
{
private:
#pragma region is_observing
	template &lt; typename TObserverSubjectList, typename TSubject &gt;
	struct is_observing_impl;

	template &lt; template&lt;typename...&gt; typename TObserverSubjectList, typename TSubject, typename... TSubjectListTail &gt;
	struct is_observing_impl&lt;TObserverSubjectList&lt;TSubject, TSubjectListTail...&gt;, TSubject&gt; : std::true_type {};

	template &lt; template&lt;typename...&gt; typename TObserverSubjectList, typename TSubject &gt;
	struct is_observing_impl&lt;TObserverSubjectList&lt;&gt;, TSubject&gt; : std::false_type {};

	template &lt; template&lt;typename...&gt; typename TObserverSubjectList, typename TSubject, typename TSubjectListHead, typename... TSubjectListTail &gt;
	struct is_observing_impl&lt;TObserverSubjectList&lt;TSubjectListHead, TSubjectListTail...&gt;, TSubject&gt; : is_observing_impl&lt;TObserverSubjectList&lt;TSubjectListTail...&gt;, TSubject&gt; {};

	template &lt; typename TObserver, typename TSubject &gt;
	using is_observing = std::conditional_t&lt;is_observing_impl&lt;typename TObserver::SubjectList, TSubject&gt;::value, std::tuple&lt;TObserver&gt;, std::tuple&lt;&gt;&gt;;
#pragma endregion

#pragma region is_observing_filter
	template &lt; typename TObserverList, typename TSubject &gt;
	struct is_observing_filter;

	template &lt; template&lt;typename...&gt; typename TObserverList, typename TSubject, typename... TObservers &gt;
	struct is_observing_filter&lt;TObserverList&lt;TObservers...&gt;, TSubject&gt;
	{
		using type = decltype(std::tuple_cat(std::declval&lt;is_observing&lt;TObservers, TSubject&gt;&gt;()...));
	};

	template &lt; typename TObserverList, typename TSubject &gt;
	using is_observing_filter_t = typename is_observing_filter&lt;TObserverList, TSubject&gt;::type;
#pragma endregion

#pragma region observer_list
	template &lt; typename TSubjectList &gt;
	struct observer_list;

	template &lt; template&lt;typename...&gt; typename TSubjectList, typename... TSubjects &gt;
	struct observer_list&lt;TSubjectList&lt;TSubjects...&gt;&gt;
	{
		using type = decltype(std::make_tuple(std::declval&lt;is_observing_filter_t&lt;TObserverList, TSubjects&gt;&gt;()...));
	};

public:
	using observer_list_t = typename observer_list&lt;TSubjectList&gt;::type;
#pragma endregion
};
</code></pre>
<p>Mit folgendem Test erhält man ein positives Ergebnis ( true ) :</p>
<pre><code>int main()
{
	SubjectManager&lt;ObserverList, SubjectList&gt; sm;

	std::cout &lt;&lt; std::boolalpha &lt;&lt; std::is_same&lt;decltype(sm)::observer_list_t, std::tuple&lt;std::tuple&lt;ObserverOne&gt;, std::tuple&lt;ObserverOne, ObserverTwo&gt;, std::tuple&lt;ObserverTwo&gt;&gt;&gt;::value &lt;&lt; &quot;\n\n&quot;;

	system(&quot;Pause&quot;);

	return 0;
}
</code></pre>
<p>observer_list_t ist also ein Tuple von mehreren Tuplen, wobei der jeweilige Index für die Id des Subjektes steht. ( Die Id des Subjektes kann man z.B. mit der einfachen Meta-Function &quot;Index&quot; erhalten ).</p>
<pre><code>namespace impl
		{
			template &lt; typename List, typename T &gt;
			struct IndexImpl;

			template &lt; template&lt;typename...&gt; typename List, typename T, typename... Ts &gt;
			struct IndexImpl&lt;List&lt;T, Ts...&gt;, T&gt; : std::integral_constant&lt;std::size_t, 0&gt; {};

			template &lt; template&lt;typename...&gt; typename List, typename T, typename U, typename... Us &gt;
			struct IndexImpl&lt;List&lt;U, Us...&gt;, T&gt; : std::integral_constant&lt;std::size_t, 1 + IndexImpl&lt;List&lt;Us...&gt;, T&gt;::value&gt; {};
		} // namespace impl

		template &lt; typename List, typename T &gt;
		using Index = impl::IndexImpl&lt;List, T&gt;;
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/topic/339873/beobachterliste-zur-kompilierzeit-template-meta-programming</link><generator>RSS for Node</generator><lastBuildDate>Sat, 11 Apr 2026 15:21:42 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/339873.rss" rel="self" type="application/rss+xml"/><pubDate>Tue, 04 Oct 2016 20:20:53 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Beobachterliste zur Kompilierzeit ( Template-Meta Programming ) on Tue, 04 Oct 2016 20:20:53 GMT]]></title><description><![CDATA[<p>Hallo C++ Forum,<br />
für ein momentanes Projekt habe ich angefangen ein Beobachter System zu schreiben, welches den Vorteil hat, dass man die einzelnen Beobachter nicht zur Laufzeit bei den Subjekten anmelden muss. Die Namen in dem Beispiel sind extra so gewählt, dass alles verständlich sein sollte ( normalerweise würde ich natürlich T, U, Ts, Us etc als Parameter verwenden ). Soweit scheint alles zu funktionieren und wollte einfach mal ein wenig Feedback zur Art und Weise der Lösung bekommen <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f603.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--grinning_face_with_big_eyes"
      title=":D"
      alt="😃"
    /></p>
<pre><code>class SubjectOne {};
class SubjectTwo {};
class SubjectThree {};

template &lt; typename... TSubjects &gt;
class Observer
{
public:
	using SubjectList = std::tuple&lt;TSubjects...&gt;;
};

using ObserverOne = Observer&lt;SubjectOne, SubjectTwo&gt;;
using ObserverTwo = Observer&lt;SubjectTwo, SubjectThree&gt;;

using ObserverList = std::tuple&lt;ObserverOne, ObserverTwo&gt;;
using SubjectList  = std::tuple&lt;SubjectOne, SubjectTwo, SubjectThree&gt;;

template &lt; typename TObserverList, typename TSubjectList &gt;
class SubjectManager
{
private:
#pragma region is_observing
	template &lt; typename TObserverSubjectList, typename TSubject &gt;
	struct is_observing_impl;

	template &lt; template&lt;typename...&gt; typename TObserverSubjectList, typename TSubject, typename... TSubjectListTail &gt;
	struct is_observing_impl&lt;TObserverSubjectList&lt;TSubject, TSubjectListTail...&gt;, TSubject&gt; : std::true_type {};

	template &lt; template&lt;typename...&gt; typename TObserverSubjectList, typename TSubject &gt;
	struct is_observing_impl&lt;TObserverSubjectList&lt;&gt;, TSubject&gt; : std::false_type {};

	template &lt; template&lt;typename...&gt; typename TObserverSubjectList, typename TSubject, typename TSubjectListHead, typename... TSubjectListTail &gt;
	struct is_observing_impl&lt;TObserverSubjectList&lt;TSubjectListHead, TSubjectListTail...&gt;, TSubject&gt; : is_observing_impl&lt;TObserverSubjectList&lt;TSubjectListTail...&gt;, TSubject&gt; {};

	template &lt; typename TObserver, typename TSubject &gt;
	using is_observing = std::conditional_t&lt;is_observing_impl&lt;typename TObserver::SubjectList, TSubject&gt;::value, std::tuple&lt;TObserver&gt;, std::tuple&lt;&gt;&gt;;
#pragma endregion

#pragma region is_observing_filter
	template &lt; typename TObserverList, typename TSubject &gt;
	struct is_observing_filter;

	template &lt; template&lt;typename...&gt; typename TObserverList, typename TSubject, typename... TObservers &gt;
	struct is_observing_filter&lt;TObserverList&lt;TObservers...&gt;, TSubject&gt;
	{
		using type = decltype(std::tuple_cat(std::declval&lt;is_observing&lt;TObservers, TSubject&gt;&gt;()...));
	};

	template &lt; typename TObserverList, typename TSubject &gt;
	using is_observing_filter_t = typename is_observing_filter&lt;TObserverList, TSubject&gt;::type;
#pragma endregion

#pragma region observer_list
	template &lt; typename TSubjectList &gt;
	struct observer_list;

	template &lt; template&lt;typename...&gt; typename TSubjectList, typename... TSubjects &gt;
	struct observer_list&lt;TSubjectList&lt;TSubjects...&gt;&gt;
	{
		using type = decltype(std::make_tuple(std::declval&lt;is_observing_filter_t&lt;TObserverList, TSubjects&gt;&gt;()...));
	};

public:
	using observer_list_t = typename observer_list&lt;TSubjectList&gt;::type;
#pragma endregion
};
</code></pre>
<p>Mit folgendem Test erhält man ein positives Ergebnis ( true ) :</p>
<pre><code>int main()
{
	SubjectManager&lt;ObserverList, SubjectList&gt; sm;

	std::cout &lt;&lt; std::boolalpha &lt;&lt; std::is_same&lt;decltype(sm)::observer_list_t, std::tuple&lt;std::tuple&lt;ObserverOne&gt;, std::tuple&lt;ObserverOne, ObserverTwo&gt;, std::tuple&lt;ObserverTwo&gt;&gt;&gt;::value &lt;&lt; &quot;\n\n&quot;;

	system(&quot;Pause&quot;);

	return 0;
}
</code></pre>
<p>observer_list_t ist also ein Tuple von mehreren Tuplen, wobei der jeweilige Index für die Id des Subjektes steht. ( Die Id des Subjektes kann man z.B. mit der einfachen Meta-Function &quot;Index&quot; erhalten ).</p>
<pre><code>namespace impl
		{
			template &lt; typename List, typename T &gt;
			struct IndexImpl;

			template &lt; template&lt;typename...&gt; typename List, typename T, typename... Ts &gt;
			struct IndexImpl&lt;List&lt;T, Ts...&gt;, T&gt; : std::integral_constant&lt;std::size_t, 0&gt; {};

			template &lt; template&lt;typename...&gt; typename List, typename T, typename U, typename... Us &gt;
			struct IndexImpl&lt;List&lt;U, Us...&gt;, T&gt; : std::integral_constant&lt;std::size_t, 1 + IndexImpl&lt;List&lt;Us...&gt;, T&gt;::value&gt; {};
		} // namespace impl

		template &lt; typename List, typename T &gt;
		using Index = impl::IndexImpl&lt;List, T&gt;;
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2510570</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2510570</guid><dc:creator><![CDATA[Yamahari]]></dc:creator><pubDate>Tue, 04 Oct 2016 20:20:53 GMT</pubDate></item></channel></rss>