<?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[Obskure Überlegungen: exception safety std::less und andere basic relational operator wrappers]]></title><description><![CDATA[<p>Als ich eines schönen Sommermorgens aufwachte, konnte ich eine Frage, die sich in meine Gedanken geschlichen hat, einfach nicht loswerden: &quot;Wie ist das mit der exception guarantee bei std::less?&quot;. Nun, mir ist klar, dass das in der Praxis keine Rolle spielt, aber nebenbei hat es mich interessiert. Es ist klar, dass exceptions fliegen können, wenn der operator&lt; wirft, aber was sagt der Standard ansonsten? Ich sehe jedenfalls nirgendwo Angaben, die garantieren, dass std::less(oder die anderen function objects aus demselben Abschnitt) nur werfen, wenn der genutzte operator wirft. Würde das nicht implizieren, dass selbst std::less&lt;int&gt; werfen kann?</p>
<p>Keine ernste Sache, ich bin nur neugierig. Ich kenne jedenfalls keinen Compiler bei dem std::less nicht als</p>
<pre><code>template&lt;typename T&gt;
struct less
{
    bool operator ()(const T&amp; l, const T&amp; r) {return l &lt; r;}
};
</code></pre>
<p>implementiert wäre.</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/317973/obskure-überlegungen-exception-safety-std-less-und-andere-basic-relational-operator-wrappers</link><generator>RSS for Node</generator><lastBuildDate>Mon, 27 Jul 2026 19:48:36 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/317973.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 26 Jun 2013 13:15:14 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Obskure Überlegungen: exception safety std::less und andere basic relational operator wrappers on Wed, 26 Jun 2013 13:15:14 GMT]]></title><description><![CDATA[<p>Als ich eines schönen Sommermorgens aufwachte, konnte ich eine Frage, die sich in meine Gedanken geschlichen hat, einfach nicht loswerden: &quot;Wie ist das mit der exception guarantee bei std::less?&quot;. Nun, mir ist klar, dass das in der Praxis keine Rolle spielt, aber nebenbei hat es mich interessiert. Es ist klar, dass exceptions fliegen können, wenn der operator&lt; wirft, aber was sagt der Standard ansonsten? Ich sehe jedenfalls nirgendwo Angaben, die garantieren, dass std::less(oder die anderen function objects aus demselben Abschnitt) nur werfen, wenn der genutzte operator wirft. Würde das nicht implizieren, dass selbst std::less&lt;int&gt; werfen kann?</p>
<p>Keine ernste Sache, ich bin nur neugierig. Ich kenne jedenfalls keinen Compiler bei dem std::less nicht als</p>
<pre><code>template&lt;typename T&gt;
struct less
{
    bool operator ()(const T&amp; l, const T&amp; r) {return l &lt; r;}
};
</code></pre>
<p>implementiert wäre.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2334518</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2334518</guid><dc:creator><![CDATA[Flashput]]></dc:creator><pubDate>Wed, 26 Jun 2013 13:15:14 GMT</pubDate></item><item><title><![CDATA[Reply to Obskure Überlegungen: exception safety std::less und andere basic relational operator wrappers on Wed, 26 Jun 2013 13:52:45 GMT]]></title><description><![CDATA[<blockquote>
<p>Würde das nicht implizieren, dass selbst std::less&lt;int&gt; werfen kann?</p>
</blockquote>
<p>Nein. Nur weil nicht jede minimale Funktion (und besonders jedes Funktionstemplate) noexcept-spezifiziert ist, heißt das nicht, dass sie auch theoretisch alle werfen können. Ein Großteil hat keine einzige Operation, die eine Exception werfen könnte.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2334531</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2334531</guid><dc:creator><![CDATA[Sone]]></dc:creator><pubDate>Wed, 26 Jun 2013 13:52:45 GMT</pubDate></item><item><title><![CDATA[Reply to Obskure Überlegungen: exception safety std::less und andere basic relational operator wrappers on Wed, 26 Jun 2013 13:57:44 GMT]]></title><description><![CDATA[<p>Es ist erlaubt, eine weitere Spezialisierung zu less&lt;&gt; im namespace std hinzuzufügen. Die kann natürlich werfen, auch wenn operator&lt; in dem Fall nicht werfen dürfte.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2334535</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2334535</guid><dc:creator><![CDATA[sommermorgen]]></dc:creator><pubDate>Wed, 26 Jun 2013 13:57:44 GMT</pubDate></item><item><title><![CDATA[Reply to Obskure Überlegungen: exception safety std::less und andere basic relational operator wrappers on Thu, 27 Jun 2013 14:56:39 GMT]]></title><description><![CDATA[<p>Schade, dass es da wirklich nichts gibt. Nunja, nichts womit man nicht leben kann, es gibt schließlich immer einen Weg.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2334802</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2334802</guid><dc:creator><![CDATA[Flashput]]></dc:creator><pubDate>Thu, 27 Jun 2013 14:56:39 GMT</pubDate></item><item><title><![CDATA[Reply to Obskure Überlegungen: exception safety std::less und andere basic relational operator wrappers on Thu, 27 Jun 2013 15:11:37 GMT]]></title><description><![CDATA[<p>Ja, <code>std::less&lt;int&gt;</code> kann laut Standard werfen. Nur weil es jetzt werfen kann wird keiner wahnsinnig und geht auch davon aus. Außerdem ist es der Einfachkeit halber eben auch nicht spezifiziert.</p>
<p>Vielleicht wird in Zukunft mal noch <code>noexcept(noexcept(lhs &lt; rhs))</code> o.ä. ergänzt. Dafür gibt es aber mMn. keinen Grund.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2334806</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2334806</guid><dc:creator><![CDATA[Sone]]></dc:creator><pubDate>Thu, 27 Jun 2013 15:11:37 GMT</pubDate></item><item><title><![CDATA[Reply to Obskure Überlegungen: exception safety std::less und andere basic relational operator wrappers on Thu, 27 Jun 2013 15:29:34 GMT]]></title><description><![CDATA[<p>Ich glaube nicht, dass die besagten Funktionsobjekte selbst werfen dürfen.</p>
<p>n3337 schrieb:</p>
<blockquote>
<p>17.6.5.12 Restrictions on exception handling [res.on.exception.handling]<br />
1 Any of the functions defined in the C++ standard library can report a failure by throwing an exception of<br />
a type described in its Throws: paragraph. An implementation may strengthen the exception-specification<br />
for a non-virtual function by adding a non-throwing noexcept-specification.</p>
</blockquote>
<p>Eine entsprechender Throws-Abschnitt existiert für diese Objekte nicht.<br />
Zulässig ist aber nat. dass diese Funktionen per Exception <em>verlassen</em> (exit) werden, offenbar dann, wenn der aufgerufene Operator wirft.<br />
Kann aber sein, dass ich da zuviel hineininterpretiere, die Sprache für die Beschreibung der Standardbibliothek ist tendentiell weniger präzise.</p>
<p>Für eine selbst gelieferte Spezialisierung sollte das Gleiche gelten</p>
<p>n3337 schrieb:</p>
<blockquote>
<p>17.6.4.2.1 Namespace std [namespace.std]<br />
1 The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a<br />
namespace within namespace std unless otherwise specified. A program may add a template specialization<br />
for any standard library template to namespace std only <strong>if</strong> the declaration depends on a user-defined type<br />
and <strong>the specialization meets the standard library requirements for the original template</strong> and is not explicitly<br />
prohibited.181</p>
</blockquote>
]]></description><link>https://www.c-plusplus.net/forum/post/2334811</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2334811</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Thu, 27 Jun 2013 15:29:34 GMT</pubDate></item><item><title><![CDATA[Reply to Obskure Überlegungen: exception safety std::less und andere basic relational operator wrappers on Thu, 27 Jun 2013 23:20:17 GMT]]></title><description><![CDATA[<p>So wie ich den Standard interpretiere, bedeutet ein fehlender Throws-Abschnitt nicht notwendigerweise &quot;nothrow&quot;.</p>
<p>n3337 §17.6.4.8 Other functions [res.on.functions] schrieb:</p>
<blockquote>
<p>In certain cases (replacement functions, handler functions, operations on types used to instantiate standard library template components), the C++ standard library depends on components supplied by a C++ program. If these components do not meet their requirements, the Standard places no requirements on the implementation.</p>
<p>In particular, the effects are undefined in the following cases:<br />
[...]<br />
— for types used as template arguments when instantiating a template component, if the operations on the type do not implement the semantics of the applicable Requirements subclause (17.6.3.5, 23.2, 24.2, 26.2). <strong>Operations on such types can report a failure by throwing an exception unless otherwise specified</strong>.</p>
</blockquote>
<p>Soll heissen: Funktionen, die irgendwie von einem Template-Parameter abhängen können potentiell alles mögliche werfen.</p>
<p>So hat z.B. kein Container einen Trows-Abschnitt für push_back. Nicht einmal wird bad_alloc erwähnt, weil der übergebene Allocator das nicht zwingend werfen muss.</p>
<p>Meines Erachtens wäre folgendes absolut valide (weil std::less keine Requires-Clause hat):</p>
<pre><code class="language-cpp">template&lt;&gt; less&lt;MyInt&gt; {
  bool operator() { return rand()%2 ? throw &quot;hey&quot; : rand()%2; }
};
</code></pre>
<p>Was nicht erlaubt wäre, ist unter diesen Umständen std::less&lt;MyInt&gt; als Vergleichsfunktion für z.B. sort() zu verwenden (weil dafür das LessThanComparable-Konzept erfüllt sein müsste).</p>
<p>Andererseits darf <code>std::less&lt;int&gt;</code> <em>nicht</em> werfen (&quot;add a template specialization [...] only if the declaration depends on a <strong>user-defined type</strong>&quot; aus campers Zitat). less&lt;int&gt; ist immer built-in operator&lt; für ints.</p>
<p>So ganz verstehe ich die Sache auch nicht &quot;on such types&quot; bedeutet wahrscheinlich &quot;that depends directly or indirectly on such types&quot; und &quot;depends on a user-defined type&quot; bedeutet wahrscheinlich &quot;depends on a user-defined type outside of namespace std&quot;.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2334893</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2334893</guid><dc:creator><![CDATA[standonese]]></dc:creator><pubDate>Thu, 27 Jun 2013 23:20:17 GMT</pubDate></item><item><title><![CDATA[Reply to Obskure Überlegungen: exception safety std::less und andere basic relational operator wrappers on Sat, 29 Jun 2013 09:51:44 GMT]]></title><description><![CDATA[<p>n3337 schrieb:</p>
<blockquote>
<p>17.5.1.3 Requirements [structure.requirements]<br />
/6<br />
In some cases the semantic requirements are presented as C++ code. Such code is intended as a specifica-<br />
tion of equivalence of a construct to another construct, not necessarily as the way the construct must be<br />
implemented.161</p>
<p>17.5.1.4 Detailed specifications [structure.specifications]<br />
/4<br />
Whenever the Effects: element specifies that the semantics of some function F are Equivalent to some code<br />
sequence, then the various elements are interpreted as follows. If F’s semantics specifies a Requires: element,<br />
then that requirement is logically imposed prior to the equivalent-to semantics. Next, the semantics of the<br />
code sequence are determined by the Requires:, Effects:, Postconditions:, Returns:, Throws:, Complexity:,<br />
Remarks:, Error conditions:, and Notes: specified for the function invocations contained in the code sequence.[<br />
The value returned from F is specified by F’s Returns: element, or if F has no Returns: element, a non-void<br />
return from F is specified by the Returns: elements in the code sequence. <strong>If F’s semantics contains a Throws:,<br />
Postconditions:, or Complexity: element, then that supersedes any occurrences of that element in the code<br />
sequence.</strong></p>
<p>20.8.5 Comparisons [comparisons]<br />
/5<br />
template &lt;class T&gt; struct less {<br />
bool operator()(const T&amp; x, const T&amp; y) const;<br />
typedef T first_argument_type;<br />
typedef T second_argument_type;<br />
typedef bool result_type;<br />
};</p>
<p>operator() returns x &lt; y.</p>
<p>/8<br />
For templates greater, less, greater_equal, and less_equal, the specializations for any pointer type<br />
yield a total order, even if the built-in operators &lt;, &gt;, &lt;=, &gt;= do not.</p>
</blockquote>
<p>Die Spezifikation von less enthält kein Throws: Element, also ist - im Umkehrschluss - die Throws: Specifikation der angegeben Code-Sequenz anzuwenden, diese wiederum bestimmt sich nach den Throws-Spezifikation der in der Code-Sequenz enthaltenen Funktionsaufrufe.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2335179</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2335179</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Sat, 29 Jun 2013 09:51:44 GMT</pubDate></item><item><title><![CDATA[Reply to Obskure Überlegungen: exception safety std::less und andere basic relational operator wrappers on Sat, 29 Jun 2013 15:59:39 GMT]]></title><description><![CDATA[<p>camper schrieb:</p>
<blockquote>
<p>Die Spezifikation von less enthält kein Throws: Element, also ist - im Umkehrschluss - die Throws: Specifikation der angegeben Code-Sequenz anzuwenden, diese wiederum bestimmt sich nach den Throws-Spezifikation der in der Code-Sequenz enthaltenen Funktionsaufrufe.</p>
</blockquote>
<p>Das gilt aber nur für das Basistemplate std::less&lt;T&gt;. Die allgemeine Exception-Garantie von std::less lässt sich daraus nicht ableiten (siehe mein Post).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2335287</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2335287</guid><dc:creator><![CDATA[standonese]]></dc:creator><pubDate>Sat, 29 Jun 2013 15:59:39 GMT</pubDate></item><item><title><![CDATA[Reply to Obskure Überlegungen: exception safety std::less und andere basic relational operator wrappers on Sat, 29 Jun 2013 18:39:15 GMT]]></title><description><![CDATA[<p>standonese schrieb:</p>
<blockquote>
<p>camper schrieb:</p>
<blockquote>
<p>Die Spezifikation von less enthält kein Throws: Element, also ist - im Umkehrschluss - die Throws: Specifikation der angegeben Code-Sequenz anzuwenden, diese wiederum bestimmt sich nach den Throws-Spezifikation der in der Code-Sequenz enthaltenen Funktionsaufrufe.</p>
</blockquote>
<p>Das gilt aber nur für das Basistemplate std::less&lt;T&gt;. Die allgemeine Exception-Garantie von std::less lässt sich daraus nicht ableiten (siehe mein Post).</p>
</blockquote>
<p>Mir ist nicht klar, inwiefern dein Zitat relevant ist. Wir sind uns einig, dass der Nutzer eine eigene Spezialisierung von std::less für eigene Typen schreiben darf. Und solange diese Spezialisierung nicht zusammen mit irgendeiner Komponente der Standardbibliothek verwendet wird, unterliegt sie logischerweise auch keinen Restriktionen, kann also u.a. alles Mögliche werfen. Das ist allerdings relativ uninteressant und kaum das, was der OP wissen wollte.</p>
<p>Was wenn die Spezialisierung zusammen mit der Standardbibliothek verwendet werden soll?</p>
<p>n3337 schrieb:</p>
<blockquote>
<p>17.6.4.2.1 Namespace std [namespace.std]<br />
/1<br />
The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a<br />
namespace within namespace std unless otherwise specified. <strong>A program may add a template specialization</strong><br />
for any standard library template to namespace std <strong>only if</strong> the declaration depends on a user-defined type<br />
and <strong>the specialization meets the standard library requirements for the original template</strong> and is not explicitly<br />
prohibited.181</p>
</blockquote>
<p>Dein Beispiel bewahrt nicht die Semantik der Standardspezifikation, indem std::less eben nicht den jeweiligen Operator &lt; aufruft und dessen Ergebnis zurückgibt (es sei denn, dieser Operator macht genau das Gleiche).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2335322</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2335322</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Sat, 29 Jun 2013 18:39:15 GMT</pubDate></item></channel></rss>