<?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[c++11 list initialization]]></title><description><![CDATA[<p>hi,</p>
<p>ich weiß, dass die mit c++ eingeführte list initialization die mehrdeutigkeit in gewissen fällen auflöst:</p>
<pre><code>T(); // funktionsaufruf oder temporary?
T{}; // immer temporary

T(U); // funktionsdeklaration oder temporary?
T{U}; // immer temporary
</code></pre>
<p>was ich jedoch dubios finde, ist, dass folgender code nicht kompiliert:</p>
<pre><code>#include &lt;initializer_list&gt;

struct foo
{
	foo(int a, double b)
	{
	}
	foo(std::initializer_list&lt;int&gt; l)
	{
	}
};

int main()
{
	foo bar{1, 2.};
}
</code></pre>
<p>ich weiß, dass eine <code>initializer_list</code> kein narrowing zulässt, aber wieso fällt der compiler dann nicht auf den anderen konstruktor zurück? kann ich im obigen beispiel auf irgendeine weise den ersten konstruktor aufrufen, ohne die alte schreibweise mit den klammern verwenden zu müssen?<br />
und was ist allgemein die regel dahinter, wann welcher konstruktor bei list initialization auserwählt wird?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/339325/c-11-list-initialization</link><generator>RSS for Node</generator><lastBuildDate>Sun, 12 Apr 2026 05:56:47 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/339325.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 21 Aug 2016 00:06:28 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to c++11 list initialization on Sun, 21 Aug 2016 00:06:28 GMT]]></title><description><![CDATA[<p>hi,</p>
<p>ich weiß, dass die mit c++ eingeführte list initialization die mehrdeutigkeit in gewissen fällen auflöst:</p>
<pre><code>T(); // funktionsaufruf oder temporary?
T{}; // immer temporary

T(U); // funktionsdeklaration oder temporary?
T{U}; // immer temporary
</code></pre>
<p>was ich jedoch dubios finde, ist, dass folgender code nicht kompiliert:</p>
<pre><code>#include &lt;initializer_list&gt;

struct foo
{
	foo(int a, double b)
	{
	}
	foo(std::initializer_list&lt;int&gt; l)
	{
	}
};

int main()
{
	foo bar{1, 2.};
}
</code></pre>
<p>ich weiß, dass eine <code>initializer_list</code> kein narrowing zulässt, aber wieso fällt der compiler dann nicht auf den anderen konstruktor zurück? kann ich im obigen beispiel auf irgendeine weise den ersten konstruktor aufrufen, ohne die alte schreibweise mit den klammern verwenden zu müssen?<br />
und was ist allgemein die regel dahinter, wann welcher konstruktor bei list initialization auserwählt wird?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2506079</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2506079</guid><dc:creator><![CDATA[ahnungs loser]]></dc:creator><pubDate>Sun, 21 Aug 2016 00:06:28 GMT</pubDate></item><item><title><![CDATA[Reply to c++11 list initialization on Sun, 21 Aug 2016 00:27:17 GMT]]></title><description><![CDATA[<p>ahnungs loser schrieb:</p>
<blockquote>
<p>die mit c++ eingeführte list initialization</p>
</blockquote>
<p>*die mit c++11 eingeführte</p>
<p>ahnungs loser schrieb:</p>
<blockquote>
<p>ohne die alte schreibweise mit den klammern verwenden zu müssen?</p>
</blockquote>
<p>*mit den runden klammern ()</p>
<p>noch was das narrowing angeht: wieso geht dann wiederum das hier?</p>
<pre><code>struct foo
{
	foo(unsigned, unsigned)
	{
	}
};

int main()
{
	foo{1, 2};
}
</code></pre>
<p><code>int</code> zu <code>unsigned</code> ist ja auch narrowing, hier beschwert sich der compiler aber nicht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2506081</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2506081</guid><dc:creator><![CDATA[ahnungs loser]]></dc:creator><pubDate>Sun, 21 Aug 2016 00:27:17 GMT</pubDate></item><item><title><![CDATA[Reply to c++11 list initialization on Sun, 21 Aug 2016 01:25:32 GMT]]></title><description><![CDATA[<p>ahnungs loser schrieb:</p>
<blockquote>
<p>hi,</p>
<p>ich weiß, dass die mit c++ eingeführte list initialization die mehrdeutigkeit in gewissen fällen auflöst:</p>
<p>ich weiß, dass eine <code>initializer_list</code> kein narrowing zulässt, aber wieso fällt der compiler dann nicht auf den anderen konstruktor zurück?</p>
</blockquote>
<p>Weil narrowing erst eine Rolle spielt, <em>nachdem</em> der passende Konstruktor ausgewählt wurde. Die Konvertierungen sind ja <em>möglich</em>, nur eben verboten.</p>
<p>ahnungs loser schrieb:</p>
<blockquote>
<p>kann ich im obigen beispiel auf irgendeine weise den ersten konstruktor aufrufen, ohne die alte schreibweise mit den klammern verwenden zu müssen?</p>
</blockquote>
<p>nein.</p>
<p>ahnungs loser schrieb:</p>
<blockquote>
<p>und was ist allgemein die regel dahinter, wann welcher konstruktor bei list initialization auserwählt wird?</p>
</blockquote>
<p>Wenn initializer_list-Konstruktoren vorhanden sind und list-Initialisierung stattfindet, wird zuerst geschaut, ob bei Betrachtung nur dieser Konstruktoren die Überladung aufgelöst werden kann, und nur wenn das nicht der Fall ist, werden auch alle anderen Konstruktoren einbezogen.</p>
<p>Man könnte folgendes tun:</p>
<pre><code class="language-cpp">#include &lt;initializer_list&gt;
#include &lt;type_traits&gt;

struct foo
{
    foo(int a, double b)
    {
    }
    template &lt;typename T, typename std::enable_if&lt;std::is_same&lt;T, int&gt;{}, int&gt;::type = 0&gt;
    foo(std::initializer_list&lt;T&gt; l)
    {
    }
};

int main()
{
    foo bar{1, 2.};
}
</code></pre>
<p>das ist aber nicht sonderlich toll, weil der initializer_list-Konstruktor nun überhaupt keine Konvertierungen (nicht nur die narrowing Konvertierungen) mehr zulässt.<br />
Das ist alles furchtbar-<br />
Als Faustregel: Wenn neben einem initializer_list-Konstruktor noch andere Konstruktoren gebraucht werden, ist es zweckmäßig, zu prüfen, ob nicht besser ein Templatekonstruktor mit entsprechendem Parameterpack verwendet werden kann.</p>
<blockquote>
<p>int zu unsigned ist ja auch narrowing, hier beschwert sich der compiler aber nicht.</p>
</blockquote>
<p>Weil die Initialisierer konstante Ausdrücke sind und ihre Werte in den Zieltyp passen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2506082</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2506082</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Sun, 21 Aug 2016 01:25:32 GMT</pubDate></item><item><title><![CDATA[Reply to c++11 list initialization on Sun, 21 Aug 2016 02:53:06 GMT]]></title><description><![CDATA[<p>danke für die erklärung, sehr einleuchtend. etwas noch: soll ich nun in meinem code durchgängig list initialization verwenden und nur in den sonderfällen (z.b. wenn ich einen vector&lt;int&gt; initialisiere) ausweichen oder soll ich generell bei der alten schreibweise bleiben und nur wechseln, wenn ich mir damit tipparbeit sparen kann?</p>
<p>ps: noch ein kleiner spezialfall hier:</p>
<pre><code>#include &lt;initializer_list&gt;

class nonaggregate
{
	int a, b;

public:
	nonaggregate(int a, int b)
		: a(a), b(b)
	{
	}
};

nonaggregate f()
{
	auto&amp;&amp; ret = { 1, 2 };
	return ret; // kompiliert nicht

	return { 1, 2 }; // kompiliert
}

auto g()
{
	return { 1, 2 }; // kompiliert nicht
}

int main()
{
}
</code></pre>
<p>ich vermute, der ausdruck <code>{ 1, 2 }</code> an sich hat keinen datentyp. laut [list=http://en.cppreference.com/w/cpp/utility/initializer_list]dieser quelle[/list] wird hingegen eine <code>std::initializer_list</code> erzeugt, wenn jener ausdruck an ein <code>auto</code> gebunden wird (so, wie in f). wieso aber trifft dies nicht auf g zu?<br />
was mich ausserdem verwundert, ist, welche grammatikregel die return-anweisung in f erlaubt. hat diese art von kontext, sowie auch ein non-deduced parameter, dem man diesen typenlosen ausdruck ebenfalls übergeben darf, einen speziellen namen?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2506086</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2506086</guid><dc:creator><![CDATA[ahnungs loser]]></dc:creator><pubDate>Sun, 21 Aug 2016 02:53:06 GMT</pubDate></item><item><title><![CDATA[Reply to c++11 list initialization on Sun, 21 Aug 2016 05:03:47 GMT]]></title><description><![CDATA[<p>ahnungs loser schrieb:</p>
<blockquote>
<p>ich vermute, der ausdruck <code>{ 1, 2 }</code> an sich hat keinen datentyp.</p>
</blockquote>
<p>Es ist nicht einmal ein Ausdruck.</p>
<p>ahnungs loser schrieb:</p>
<blockquote>
<p>laut [list=http://en.cppreference.com/w/cpp/utility/initializer_list]dieser quelle[/list] wird hingegen eine <code>std::initializer_list</code> erzeugt, wenn jener ausdruck an ein <code>auto</code> gebunden wird (so, wie in f).</p>
</blockquote>
<p>richtig.</p>
<p>ahnungs loser schrieb:</p>
<blockquote>
<p>wieso aber trifft dies nicht auf g zu?</p>
</blockquote>
<p>weil der Standard es verbietet.</p>
<blockquote>
<p>If the deduction is for a return statement and the initializer is a braced-init-list (8.5.4), the program is ill-formed.</p>
</blockquote>
<p>ahnungs loser schrieb:</p>
<blockquote>
<p>was mich ausserdem verwundert, ist, welche grammatikregel die return-anweisung in f erlaubt.</p>
</blockquote>
<p>Diejenige, die besagt, dass auf ein return ein Ausdruck oder eine solche Initialisierungsliste folgen darf.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2506087</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2506087</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Sun, 21 Aug 2016 05:03:47 GMT</pubDate></item></channel></rss>