<?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[Template Variant Parameter Auflösung]]></title><description><![CDATA[<p>Ich befasse mich seit Kurzem mit Templates Variants unter C++11. Nun möchte ich ein Objekt T per Lambda Expression erzeugen dessen Konstruktor Argumente ich dynamisch zur Laufzeit auflöse um Dependency Injection über einen IOC Container nachzubilden.</p>
<p>Ich habe folgende Konstrukte:</p>
<pre><code>struct A{};
struct B{};

struct C
{
	C(std::shared_ptr&lt;A&gt; a, std::shared_ptr&lt;B&gt; b)
	:m_a(a), m_b(b){}

	std::shared_ptr&lt;A&gt; m_a = nullptr;
	std::shared_ptr&lt;B&gt; m_b = nullptr;
};
</code></pre>
<p>Nun möchte ich ein Objekt vom Typ C erzeugen, dessen Abhängigkeiten A und B ich dynamisch zur Laufzeit bestimme. Das funktioniert bestens sofern ich den konkreten Typen von A und B kenne. Hierfür habe ich mir folgende Funktion gebaut:</p>
<pre><code>template &lt;typename T&gt;
std::shared_ptr&lt;T&gt; resolve(void) const
{
     return std::make_shared&lt;T&gt;();
}

template &lt;typename T, typename ... D&gt;
void wire(void)
{
     auto delegate = [this]() -&gt; T * {
         return new T(this-&gt;resolve&lt;D&gt;()...);
     };
}
</code></pre>
<p>Nun habe ich aber den Fall, dass ich auch verschiedene Typen Ausprägungen habe, die ich über einen Namen unterscheide und über diesen Namen auflösen kann. Hiefür habe ich eine weitere Resolve Funktion:</p>
<pre><code>template &lt;typename T&gt;
std::shared_ptr&lt;T&gt; resolve(const std::string&amp; name) const
{
     ...
}
</code></pre>
<p>Nur wie bekomme ich das mit meiner Wire-Funktion verheiratet? Ich hatte mir gedacht ein separates Template hierfür zu nuzten, das den Zieltypen kennt und selber ein logischen Container abbildet, der alle relevanten Daten hält (u.A. den möglichen Namen).</p>
<pre><code>template &lt;typename T&gt;
struct Dependency
{
	Dependency(const std::string&amp; name)
        :m_type(typeid(T)), m_name(name){}

	std::type_index m_type;
        std::string m_name = &quot;undefined&quot;;
};
</code></pre>
<p>So dass ich folgenden wire Aufruf erhalte:</p>
<pre><code>template &lt;typename D&gt;
    D resolve(const D&amp; dependency) { 
      ...  hier D auswerten und konkretes Resultat zurückgeben ...
    } 

    template &lt;typename T, typename... D&gt;
    void wire(const D&amp;... dependency)
    {
       auto delegate = [&amp;] {
           return new T(this-&gt;resolve(dependency)...);
       };

       delegate();	   
    }
</code></pre>
<p>Das mag der Compiler jedoch nicht, da er im lambda Ausdruck die Abhängigkeit nicht in den Rückgabewert des resolve Aufrufes überführt sondern D ... durch die konkreten dependencies ergänzt die der C Konstruktor nicht kennt ...</p>
<blockquote>
<p>test.cpp: In instantiation of 'X::wire(const D&amp; ...)::&lt;lambda()&gt; [with T = C; D = {DEP&lt;A&gt;, DEP&lt;B&gt;}]':<br />
test.cpp:89:39: required from 'struct X::wire(const D&amp; ...) [with T = C; D = {DEP&lt;A&gt;, DEP&lt;B&gt;}]::&lt;lambda()&gt;'<br />
test.cpp:90:8: required from 'void X::wire(const D&amp; ...) [with T = C; D = {DEP&lt;A&gt;, DEP&lt;B&gt;}]'<br />
test.cpp:136:26: required from here<br />
test.cpp:90:8: error: no matching function for call to 'C::C(DEP&lt;A1&gt;, {DEP&lt;A&gt;, DEP&lt;B&gt;})'</p>
</blockquote>
<p>Ist mein Vorhaben überhaupt möglich? Wenn ja wie?</p>
<p>~Edit v. Arcoth, Code-Tags~</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/327745/template-variant-parameter-auflösung</link><generator>RSS for Node</generator><lastBuildDate>Wed, 08 Jul 2026 23:53:11 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/327745.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 01 Sep 2014 21:02:28 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Template Variant Parameter Auflösung on Tue, 02 Sep 2014 10:35:34 GMT]]></title><description><![CDATA[<p>Ich befasse mich seit Kurzem mit Templates Variants unter C++11. Nun möchte ich ein Objekt T per Lambda Expression erzeugen dessen Konstruktor Argumente ich dynamisch zur Laufzeit auflöse um Dependency Injection über einen IOC Container nachzubilden.</p>
<p>Ich habe folgende Konstrukte:</p>
<pre><code>struct A{};
struct B{};

struct C
{
	C(std::shared_ptr&lt;A&gt; a, std::shared_ptr&lt;B&gt; b)
	:m_a(a), m_b(b){}

	std::shared_ptr&lt;A&gt; m_a = nullptr;
	std::shared_ptr&lt;B&gt; m_b = nullptr;
};
</code></pre>
<p>Nun möchte ich ein Objekt vom Typ C erzeugen, dessen Abhängigkeiten A und B ich dynamisch zur Laufzeit bestimme. Das funktioniert bestens sofern ich den konkreten Typen von A und B kenne. Hierfür habe ich mir folgende Funktion gebaut:</p>
<pre><code>template &lt;typename T&gt;
std::shared_ptr&lt;T&gt; resolve(void) const
{
     return std::make_shared&lt;T&gt;();
}

template &lt;typename T, typename ... D&gt;
void wire(void)
{
     auto delegate = [this]() -&gt; T * {
         return new T(this-&gt;resolve&lt;D&gt;()...);
     };
}
</code></pre>
<p>Nun habe ich aber den Fall, dass ich auch verschiedene Typen Ausprägungen habe, die ich über einen Namen unterscheide und über diesen Namen auflösen kann. Hiefür habe ich eine weitere Resolve Funktion:</p>
<pre><code>template &lt;typename T&gt;
std::shared_ptr&lt;T&gt; resolve(const std::string&amp; name) const
{
     ...
}
</code></pre>
<p>Nur wie bekomme ich das mit meiner Wire-Funktion verheiratet? Ich hatte mir gedacht ein separates Template hierfür zu nuzten, das den Zieltypen kennt und selber ein logischen Container abbildet, der alle relevanten Daten hält (u.A. den möglichen Namen).</p>
<pre><code>template &lt;typename T&gt;
struct Dependency
{
	Dependency(const std::string&amp; name)
        :m_type(typeid(T)), m_name(name){}

	std::type_index m_type;
        std::string m_name = &quot;undefined&quot;;
};
</code></pre>
<p>So dass ich folgenden wire Aufruf erhalte:</p>
<pre><code>template &lt;typename D&gt;
    D resolve(const D&amp; dependency) { 
      ...  hier D auswerten und konkretes Resultat zurückgeben ...
    } 

    template &lt;typename T, typename... D&gt;
    void wire(const D&amp;... dependency)
    {
       auto delegate = [&amp;] {
           return new T(this-&gt;resolve(dependency)...);
       };

       delegate();	   
    }
</code></pre>
<p>Das mag der Compiler jedoch nicht, da er im lambda Ausdruck die Abhängigkeit nicht in den Rückgabewert des resolve Aufrufes überführt sondern D ... durch die konkreten dependencies ergänzt die der C Konstruktor nicht kennt ...</p>
<blockquote>
<p>test.cpp: In instantiation of 'X::wire(const D&amp; ...)::&lt;lambda()&gt; [with T = C; D = {DEP&lt;A&gt;, DEP&lt;B&gt;}]':<br />
test.cpp:89:39: required from 'struct X::wire(const D&amp; ...) [with T = C; D = {DEP&lt;A&gt;, DEP&lt;B&gt;}]::&lt;lambda()&gt;'<br />
test.cpp:90:8: required from 'void X::wire(const D&amp; ...) [with T = C; D = {DEP&lt;A&gt;, DEP&lt;B&gt;}]'<br />
test.cpp:136:26: required from here<br />
test.cpp:90:8: error: no matching function for call to 'C::C(DEP&lt;A1&gt;, {DEP&lt;A&gt;, DEP&lt;B&gt;})'</p>
</blockquote>
<p>Ist mein Vorhaben überhaupt möglich? Wenn ja wie?</p>
<p>~Edit v. Arcoth, Code-Tags~</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2415734</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2415734</guid><dc:creator><![CDATA[Hellhound_01]]></dc:creator><pubDate>Tue, 02 Sep 2014 10:35:34 GMT</pubDate></item><item><title><![CDATA[Reply to Template Variant Parameter Auflösung on Tue, 02 Sep 2014 10:22:46 GMT]]></title><description><![CDATA[<p>Kannst du das evtl. in einem zusammenhängenden minimalen Code transformieren? Ist ein bisschen schwierig, beim Lesen mehrere Codeblöcke gleichzeitig zu überblicken.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2415789</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2415789</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Tue, 02 Sep 2014 10:22:46 GMT</pubDate></item><item><title><![CDATA[Reply to Template Variant Parameter Auflösung on Tue, 02 Sep 2014 10:36:50 GMT]]></title><description><![CDATA[<p>Habe dir Code-Tags spendiert.</p>
<p>Ich stimme camper zu, habe aber noch eine Frage:</p>
<pre><code>template &lt;typename D&gt;
    D resolve(const D&amp; dependency) { 
      ...  hier D auswerten und konkretes Resultat zurückgeben ...
    }
</code></pre>
<p>Müssen nicht alle <code>resolve</code> -Funktionstemplates <code>shared_ptr</code> 's zurückgeben?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2415793</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2415793</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Tue, 02 Sep 2014 10:36:50 GMT</pubDate></item><item><title><![CDATA[Reply to Template Variant Parameter Auflösung on Tue, 02 Sep 2014 13:37:41 GMT]]></title><description><![CDATA[<p>Stimme Euch zu, war wohl gestern etwas spät. Jetzt wo ich das ganze noch einmal gelesen habe, kommt es mir auch etwas schwammig vor (zudem ist das ganze Fehlerhaft, wie Acroth es korrekt bemerkt hat) ...</p>
<p>Leider ist das Problem auch sehr komplex ... Hier einmal der Versuch es zu vereinfachen:</p>
<pre><code>#include &lt;type_traits&gt;
#include &lt;unordered_map&gt; 
#include &lt;iostream&gt; 

template &lt;typename T&gt;
struct D
{
	D(){}

	std::shared_ptr&lt;D&gt; resolve(void) {
		return std::make_shared&lt;D&gt;();
	}
};

struct X
{
    template &lt;typename T, typename ... D&gt;
    void wire(const D&amp; ... dependency){
        auto delegate = [&amp;] {
            return new T(this-&gt;resolve(dependency)...);
        };
        delegate();
    }

    template &lt;typename D&gt;
    std::shared_ptr&lt;D&gt; resolve (const D&amp; dependency){
        return dependency.resolve();
    }	
};

struct A{};
struct B{}; 
struct C
{
    C(std::shared_ptr&lt;A&gt; a, std::shared_ptr&lt;B&gt; b)
    :m_a(a), m_b(b){}

    std::shared_ptr&lt;A&gt; m_a = nullptr;
    std::shared_ptr&lt;B&gt; m_b = nullptr;
};

int main()
{
  try{
	X().wire&lt;C&gt;(D&lt;A&gt;(), D&lt;B&gt;());
  }
  catch(...){
       printf(&quot;Unknown exception caught!&quot;);
       return 1;
  }
  // return successfully
  return 0;
}
</code></pre>
<p>Ziel ist es ein transientes Objekt vom Typ C zu erstellen und dabei die Abhängigkeiten dynamisch aufzulösen. Zur Vereinfachung habe ich dem Dependency Object D eine resolve Methode verpasst, die eigentlich vom IOC Container aufgerufen werden muss.</p>
<p>Das Problem bleibt jedoch bestehen. Beim Auflösen der Lambda-Closure in der Wire-Funktion wird an den Konstruktor von C die Dependency (std::shared_ptr&lt;D&lt;A&gt; und std::shared_ptr&lt;D&lt;B&gt;&gt;) übergeben und nicht in das Ergebnis std::shared_ptr&lt;A&gt; bzw. std::shared_ptr&lt;B&gt; aufgelöst, so dass es zu folgendem Compile-Fehler kommt:</p>
<blockquote>
<p>test.cpp: In instantiation of 'X::wire(const D&amp; ...)::&lt;lambda()&gt; [with T = C; D = {D&lt;A&gt;, D&lt;B&gt;}]':<br />
test.cpp:80:40: required from 'struct X::wire(const D&amp; ...) [with T = C; D = {D&lt;A&gt;, D&lt;B&gt;}]::&lt;lambda()&gt;'<br />
test.cpp::81:9: required from 'void X::wire(const D&amp; ...) [with T = C; D = {D&lt;A&gt;, D&lt;B&gt;}]'<br />
test.cpp::111:28: required from here<br />
test.cpp::81:9: error: no matching function for call to 'C::C(std::shared_ptr&lt;D&lt;A&gt; &gt;, std::shared_ptr&lt;D&lt;B&gt; &gt;)'<br />
};<br />
^<br />
test.cpp::81:9: note: candidates are:<br />
test.cpp:<img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f4af.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--hundred_points"
      title=":100:"
      alt="💯"
    />5: note: C::C(std::shared_ptr&lt;A&gt;, std::shared_ptr&lt;B&gt;)<br />
C(std::shared_ptr&lt;A&gt; a, std::shared_ptr&lt;B&gt; b)<br />
^<br />
test.cpp:<img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f4af.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--hundred_points"
      title=":100:"
      alt="💯"
    />5: note: no known conversion for argument 1 from 'std::shared_ptr&lt;D&lt;A&gt; &gt;' to 'std::shared_ptr&lt;A&gt;<br />
test.cpp::98:8: note: C::C(const C&amp;)<br />
struct C</p>
</blockquote>
<p>Hoffe ich konnte jetzt das Ganze etwas entwirren <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2415824</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2415824</guid><dc:creator><![CDATA[Hellhound_01]]></dc:creator><pubDate>Tue, 02 Sep 2014 13:37:41 GMT</pubDate></item><item><title><![CDATA[Reply to Template Variant Parameter Auflösung on Tue, 02 Sep 2014 14:58:56 GMT]]></title><description><![CDATA[<p>Der kann D&lt;A&gt; nicht zu A konvertieren.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2415835</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2415835</guid><dc:creator><![CDATA[Nathan]]></dc:creator><pubDate>Tue, 02 Sep 2014 14:58:56 GMT</pubDate></item><item><title><![CDATA[Reply to Template Variant Parameter Auflösung on Tue, 02 Sep 2014 15:44:18 GMT]]></title><description><![CDATA[<p>sollte das nicht</p>
<pre><code>template &lt;typename T&gt;
struct D
{
	D(){}

	std::shared_ptr&lt;T&gt; resolve(void) {// !
		return std::make_shared&lt;T&gt;(); // !
	}
};
// ...

struct X
{
// ...

    template &lt;typename D&gt;
    auto resolve (const D&amp; dependency){
        return dependency.resolve();
    }  
};
</code></pre>
<p>sein?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2415840</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2415840</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Tue, 02 Sep 2014 15:44:18 GMT</pubDate></item><item><title><![CDATA[Reply to Template Variant Parameter Auflösung on Tue, 02 Sep 2014 19:15:43 GMT]]></title><description><![CDATA[<p>Danke Camper, stimmt natürlich, da hab ich etwas gepennt. Aber diese Korrektur ändert nichts, der Fehler bleibt bestehen:</p>
<blockquote>
<p>test.cpp: In instantiation of 'X::wire(const D&amp; ...)::&lt;lambda()&gt; [with T = C; D = {D&lt;A&gt;, D&lt;B&gt;}]':<br />
test.cpp:62:40: required from 'struct X::wire(const D&amp; ...) [with T = C; D = {D&lt;A&gt;, D&lt;B&gt;}]::&lt;lambda()&gt;'<br />
test.cpp:63:9: required from 'void X::wire(const D&amp; ...) [with T = C; D = {D&lt;A&gt;, D&lt;B&gt;}]'<br />
test.cpp:87:28: required from here<br />
test.cpp:63:9: error: no matching function for call to 'C::C(std::shared_ptr&lt;D&lt;A&gt; &gt;, std::shared_ptr&lt;D&lt;B&gt; &gt;)'<br />
};<br />
^<br />
test.cpp:63:9: note: candidates are:<br />
test.cpp:77:5: note: C::C(std::shared_ptr&lt;A&gt;, std::shared_ptr&lt;B&gt;)<br />
C(std::shared_ptr&lt;A&gt; a, std::shared_ptr&lt;B&gt; b)<br />
^<br />
test.cpp:77:5: note: no known conversion for argument 1 from 'std::shared_ptr&lt;D&lt;A&gt; &gt;' to 'std::shared_ptr&lt;A&gt;'<br />
test.cpp:75:8: note: C::C(const C&amp;)<br />
struct C<br />
^<br />
test.cpp:75:8: note: candidate expects 1 argument, 2 provided<br />
test.cpp:75:8: note: C::C(C&amp;&amp;)<br />
test.cpp:75:8: note: candidate expects 1 argument, 2 provided<br />
test.cpp: In instantiation of 'std::shared_ptr&lt;_Tp1&gt; X::resolve(const D&amp;) [with D = D&lt;A&gt;]':<br />
test.cpp:63:9: required from 'X::wire(const D&amp; ...)::&lt;lambda()&gt; [with T = C; D = {D&lt;A&gt;, D&lt;B&gt;}]'<br />
test.cpp:62:40: required from 'struct X::wire(const D&amp; ...) [with T = C; D = {D&lt;A&gt;, D&lt;B&gt;}]::&lt;lambda()&gt;'<br />
test.cpp.cpp:63:9: required from 'void X::wire(const D&amp; ...) [with T = C; D = {D&lt;A&gt;, D&lt;B&gt;}]'<br />
test.cpp:87:28: required from here<br />
test.cpp:69:35: error: passing 'const D&lt;A&gt;' as 'this' argument of 'std::shared_ptr&lt;_Tp1&gt; D&lt;T&gt;::resolve() [with T = A]' discards qualifiers [-fpermissive]<br />
return dependency.resolve();<br />
^<br />
test.cpp:69:35: error: could not convert 'D&lt;T&gt;::resolve() [with T = A]()' from 'std::shared_ptr&lt;A&gt;' to 'std::shared_ptr&lt;D&lt;A&gt; &gt;'<br />
test.cpp: In instantiation of 'std::shared_ptr&lt;_Tp1&gt; X::resolve(const D&amp;) [with D = D&lt;B&gt;]':<br />
test.cpp:63:9: required from 'X::wire(const D&amp; ...)::&lt;lambda()&gt; [with T = C; D = {D&lt;A&gt;, D&lt;B&gt;}]'<br />
test.cpp:62:40: required from 'struct X::wire(const D&amp; ...) [with T = C; D = {D&lt;A&gt;, D&lt;B&gt;}]::&lt;lambda()&gt;'<br />
test.cpp:63:9: required from 'void X::wire(const D&amp; ...) [with T = C; D = {D&lt;A&gt;, D&lt;B&gt;}]'<br />
test.cpp:87:28: required from here<br />
c:/binrev/repository/ioc-deps/src/signals.cpp:69:35: error: passing 'const D&lt;B&gt;' as 'this' argument of 'std::shared_ptr&lt;_Tp1&gt; D&lt;T&gt;::resolve() [with T = B]' discards qualifiers [-fpermissive]<br />
test.cpp:69:35: error: could not convert 'D&lt;T&gt;::resolve() [with T = B]()' from 'std::shared_ptr&lt;B&gt;' to 'std::shared_ptr&lt;D&lt;B&gt; &gt;'<br />
make[2]: *** [CMakeFiles/signals.dir/src/signals.cpp.obj] Error 1<br />
make[1]: *** [CMakeFiles/signals.dir/all] Error 2<br />
make: *** [all] Error 2</p>
</blockquote>
]]></description><link>https://www.c-plusplus.net/forum/post/2415868</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2415868</guid><dc:creator><![CDATA[Hellhound_01]]></dc:creator><pubDate>Tue, 02 Sep 2014 19:15:43 GMT</pubDate></item></channel></rss>