<?xml version="1.0"?>
<rss version="2.0"><channel><title>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: &#x644;&#x63A;&#x629; C++</title><link>https://academy.hsoub.com/programming/cpp/page/2/?d=2</link><description>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: &#x644;&#x63A;&#x629; C++</description><language>ar</language><item><title>&#x62F;&#x644;&#x627;&#x644;&#x627;&#x62A; &#x627;&#x644;&#x646;&#x642;&#x644; Move Semantics &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%AF%D9%84%D8%A7%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D9%86%D9%82%D9%84-move-semantics-%D9%81%D9%8A-cpp-r1023/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_03/48.png.352842a99f7e9024868422e33c51cceb.png" /></p>

<p>
	دلالات النقل هي وسيلة لنقل كائن إلى آخر في C++‎، عبر إفراغ الكائن القديم، وتبديل محتوياته بمحتويات الكائن الجديد. ولفهم دلالات النقل، من الضروري فهم المقصود <a data-ss1617022792="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-40-%D9%81%D8%A6%D8%A7%D8%AA-%D8%A7%D9%84%D9%82%D9%8A%D9%85-value-categories-%D9%81%D9%8A-cpp-r969/" rel="">بالمرجع اليميني</a> (rvalue reference). وهي، أي المراجع اليمينية (<code>‎T&amp;&amp;‎</code> حيث T يمثّل نوع الكائن) لا تختلف كثيرًا عن المراجع العادية (<code>‎T&amp;‎</code>، يُطلق عليها الآن مراجع يسارية - lvalue references)، لكنهما تتصرّفان كنوعين مختلفين. ونستطيع إنشاء مُنشئات أو دوال تأخذ أحد النوعين، وهو أمر ضروري عند التعامل مع دلالات النقل.
</p>

<p>
	ونحن نحتاج إلى نوعين مختلفين من أجل تحديد سلوكين مختلفين، إذ ترتبط مُنشئات المراجع اليسارية بالنّسخ، في حين ترتبط مُنشئات المراجع اليمينية بالنقل. ولأجل نقل كائن، سنستخدم الدالة <code>‎std::move(obj)‎</code> التي تعيد مرجعًا يمينيًا يشير إلى الكائن، ويمكننا استخدام ذلك لنقل بيانات هذا الكائن إلى كائن جديد.
</p>

<p>
	هناك عدّة طرق لفعل ذلك وسنناقشها فيما يلي، فكلّ ما عليك تذكّره الآن هو أنّ استخدام <code>‎std::move‎</code> يخلق مرجعًا يمينيًا، أي أن تعليمة <code>std::move(obj)‎</code> لا تغيّر محتوى الكائن <code>obj</code>، أمّا <code>auto obj2 = std::move(obj)‎</code> فقد تفعل ذلك.
</p>

<h2>
	استخدام std::move لتخفيض التعقيد من O(n²)‎‎ إلى O(n)‎‎
</h2>

<p>
	أدخلت C++‎ 11 دعم نقل الكائنات في اللغة الأساسية وفي المكتبة القياسية، فإذا كان لدينا كائن o مؤقّت وكنّا نريد إنشاء نسخة منطقية (logical copy) منه، فعندئذ قد يكون من الآمن أخذ موارده ببساطة، مثل المخزن المؤقّت المخصّص ديناميكيًا (dynamically allocated buﬀer) الخاص به، تاركين الكائن o فارغًا منطقيًا (logically empty)، ولكن سيبقى قابلاً للتدمير والنسخ.
</p>

<p>
	يشمل دعم اللغة الأساسية (core language) ما يلي:
</p>

<ul>
<li>
		باني نوع المراجع اليمينية (rvalue reference type builder‏) <code>‎&amp;&amp;‎</code>، على سبيل المثال، <code>‎std::string&amp;&amp;‎</code> هو مرجع يميني يشير إلى سلسلة نصية (<code>‎std::string‎</code>)، ممّا يبيّن أنّ هذا المرجع مؤقّت، ويمكن نقل موارده.
	</li>
	<li>
		دعم خاص لمنشئ النقل - move constructor‏ - <code>‎T( T&amp;&amp; )‎</code>، الذي يفترض أن ينقل الموارد بكفاءة من الكائن المُحدّد الآخر، بدلاً من نسخ تلك الموارد.
	</li>
	<li>
		دعم خاص لعامل إسناد النقل (move assignment operator‏) <code>‎auto operator=(T&amp;&amp;) -&gt; T&amp;‎</code>، والذي يفترض أيضًا أن يجري عمليّة النقل من المصدر.
	</li>
</ul>
<p>
	يتركّز الدعم الذي تقدمه المكتبة القياسية بالأساس في قالب الدالّة <code>‎std::move‎</code> من الترويسة <utility>، وتنتج هذه الدالّة مرجعًا يمينيًا يشير إلى الكائن المُحدّد، وذلك يبيّن أنّه من الممكن النقل منه كما لو كان مؤقّتًا. </utility></p>

<p>
	تعقيد (complexity) عمليّة نسخ حاوية يساوي عادةً O(n)‎‎، حيث يمثّل n عدد عناصر الحاوية، أمّا النقل فتَعقيده يساوي O(1)‎‎، أي أنّ وقته ثابت. وبالنسبة لخوارزمية تنسخ تلك الحاوية n مرّة منطقيًا، فيمكن لذلك أن يقلّل التعقيد من القيمة O (n²)‎‎ (غير العملية)، إلى التعقيد الخطي O(n)‎‎.
</p>

<p>
	قدّم أندرو كوينج (Andrew Koenig) في مقالته <a data-ss1617022792="1" href="https://www.drdobbs.com/cpp/containters-that-never-change/240161543" rel="external nofollow">“Containers That Never Change”</a> مثالًا مثيرًا للاهتمام عن عدم كفاءة الخوارزمية عند استخدام نمط برمجة خاص تكون فيه المتغيّرات غير قابلة للتغيير بعد تهيئتها، ففي مثل هذا النمط البرمجي، تُنفَّذ الحلقات (loops) بشكل عام باستخدام التكرارية، وبالنسبة لبعض الخوارزميات، مثل خوارزمية إنشاء <a data-ss1617022792="1" href="https://ar.wikipedia.org/wiki/%D8%AD%D8%AF%D8%B3%D9%8A%D8%A9_%D9%83%D9%88%D9%84%D8%A7%D8%AA%D8%B2" rel="external nofollow">تسلسل Collatz‏</a> (Collatz sequence‏)‏، يتطلب التكرار نسخ الحاوية بشكل منطقي. انظر المثال التالي المبني على مثال كوينج في الرابط أعلاه:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9527_7" style="">
<span class="kwd">namespace</span><span class="pln"> my
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Item</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> </span><span class="typ">Vector_</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="com">/*E.g. std::vector&lt;Item&gt; */</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">auto</span><span class="pln"> concat</span><span class="pun">(</span><span class="pln"> </span><span class="typ">Vector_</span><span class="str">&lt;int&gt;</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> v</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> x </span><span class="pun">)</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">Vector_</span><span class="str">&lt;int&gt;</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">auto</span><span class="pln"> result
            </span><span class="pun">{</span><span class="pln">
                v
            </span><span class="pun">};</span><span class="pln">
            result</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> result</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">auto</span><span class="pln"> collatz_aux</span><span class="pun">(</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> n</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Vector_</span><span class="str">&lt;int&gt;</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> result </span><span class="pun">)</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">Vector_</span><span class="str">&lt;int&gt;</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> result</span><span class="pun">;</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">

            </span><span class="kwd">auto</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> new_result </span><span class="pun">=</span><span class="pln"> concat</span><span class="pun">(</span><span class="pln">result</span><span class="pun">,</span><span class="pln"> n</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n </span><span class="pun">%</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> collatz_aux</span><span class="pun">(</span><span class="pln">n </span><span class="pun">/</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> new_result</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
            </span><span class="kwd">else</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> collatz_aux</span><span class="pun">(</span><span class="lit">3</span><span class="pln"> </span><span class="pun">*</span><span class="pln">n </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> new_result</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">auto</span><span class="pln"> collatz</span><span class="pun">(</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> n </span><span class="pun">)</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">Vector_</span><span class="str">&lt;int&gt;</span><span class="pln">

        </span><span class="pun">{</span><span class="pln">
            assert</span><span class="pun">(</span><span class="pln">n </span><span class="pun">!=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> collatz_aux</span><span class="pun">(</span><span class="pln">n</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Vector_</span><span class="str">&lt;int&gt;</span><span class="pln"> </span><span class="pun">());</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

    please split</span><span class="pun">,</span><span class="pln"> thi
</span><span class="pun">}</span><span class="pln">    </span><span class="com">// my فضاء الاسم</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> std</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> main</span><span class="pun">()-&gt;</span><span class="typ">int</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> x</span><span class="pun">:</span><span class="pln"> my</span><span class="pun">::</span><span class="pln">collatz</span><span class="pun">(</span><span class="lit">42</span><span class="pun">))</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        cout </span><span class="pun">&lt;&lt;</span><span class="pln"> x </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">' '</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">
42 21 64 32 16 8 4 2
</pre>

<p>
	عدد عمليات نسخ العناصر الناجمة عن نسخ المتجهات يقارب O (n ²)‎ هنا، لأنّه يساوي المجموع 1 + 2 + 3 + … n.
</p>

<p>
	باستخدام المٌصرّفين g++‎ و Visual C++‎، سيُنتج الاستدعاء الوارد أعلاه للتعبير <code>‎collatz(42)‎</code> <a data-ss1617022792="1" href="https://ar.wikipedia.org/wiki/%D8%AD%D8%AF%D8%B3%D9%8A%D8%A9_%D9%83%D9%88%D9%84%D8%A7%D8%AA%D8%B2" rel="external nofollow">تسلسل Collatz</a> مؤلفًا من 8 عناصر، وسيَنطوي على 36 عملية نسخ للعناصر (‎‎8 * 7/2 = 28، بالإضافة إلى بعض العمليات) في استدعاءات مُنشئ نسخ المتجه.
</p>

<p>
	يمكن تجنّب كل عمليات نسخ العناصر تلك عن طريق نقل المتجهات التي لم تعد هناك حاجة لقيَمِها. وكي نفعل هذا فمن الضروري إزالة <code>‎const‎</code> والرجوع إلى وسائط نوع المتجه، وتمرير المتجهات بالقيمة (by value).
</p>

<p>
	تحسَّن القيم المُعادة من الدالة تلقائيا، أما بالنسبة للاستدعاءات التي تُمرّر فيها المتجهات ثمّ لا تُستخدم مرّة أخرى في الدالّة، فما عليك سوى تطبيق <code>‎std::move‎</code> لنقل تلك المخازن المؤقّتة (buﬀers) بدلاً من نسخها:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9527_9" style="">
<span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> concat</span><span class="pun">(</span><span class="pln"> </span><span class="typ">Vector_</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> x </span><span class="pun">)-&gt;</span><span class="pln"> </span><span class="typ">Vector_</span><span class="str">&lt;int&gt;</span><span class="pln">

    </span><span class="pun">{</span><span class="pln">
        v</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span></pre>

<p>
	تنبيه: نقل كائن محلي في تعليمة <code>return</code> يمنع ترك النَّسخ، انظر <a data-ss1617022792="1" href="https://stackoverflow.com/documentation/c%2b%2b/2489/copy-elision" rel="external nofollow">الرابط التالي من SO</a>، نتابع المثال …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9527_11" style="">
<span class="com">// return move(v);</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> v</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">auto</span><span class="pln"> collatz_aux</span><span class="pun">(</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> n</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Vector_</span><span class="str">&lt;int&gt;</span><span class="pln"> result </span><span class="pun">)</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">Vector_</span><span class="str">&lt;int&gt;</span><span class="pln">

    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> result</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">auto</span><span class="pln"> new_result </span><span class="pun">=</span><span class="pln"> concat</span><span class="pun">(</span><span class="pln">move</span><span class="pun">(</span><span class="pln">result</span><span class="pun">),</span><span class="pln"> n</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">struct</span><span class="pln"> result</span><span class="pun">;</span><span class="pln">    </span><span class="com">// بعد الآن `result` التحقق من عدم استخدام</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n </span><span class="pun">%</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> collatz_aux</span><span class="pun">(</span><span class="pln">n </span><span class="pun">/</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> move</span><span class="pun">(</span><span class="pln">new_result</span><span class="pun">));</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">else</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> collatz_aux</span><span class="pun">(</span><span class="lit">3</span><span class="pln"> </span><span class="pun">*</span><span class="pln">n </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> move</span><span class="pun">(</span><span class="pln">new_result</span><span class="pun">));</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="kwd">auto</span><span class="pln"> collatz</span><span class="pun">(</span><span class="typ">int</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">-</span><span class="pln">
    </span><span class="pun">&gt;</span><span class="pln"> </span><span class="typ">Vector_</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        assert</span><span class="pun">(</span><span class="pln">n </span><span class="pun">!=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> collatz_aux</span><span class="pun">(</span><span class="pln">n</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Vector_</span><span class="str">&lt;int&gt;</span><span class="pln"> </span><span class="pun">());</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	هنا، وباستخدام المصرّفين g++‎ و Visual C++‎، فإنّ عدد عمليات نسخ العناصر الناجمة عن استدعاءات مُنشئ نسخ المتجهات يساوي 0.
</p>

<p>
	ما زال تعقيد الخوارزمية يساوي O (n)‎‎، بيْد أنّه أفضل بكثير من O (n ²)‎‎. ومع بعض الدعم من لغة C++‎، يمكننا أن نستخدم النقل ونفرض جمود المتغيّر (immutability) منذ لحظة تهيتئه وحتّى النقل النهائي، بعد ذلك، فأيّ محاولة لاستخدام هذا المُتغيّر ستُعدّ خطأ. بأي حال فإن ++C لا تدعم هذا بدءًا من الإصدار C++‎ 14.
</p>

<p>
	يمكن فرض قاعدة عدم الاستخدام بعد النقل بالنسبة للشيفرات الخالية من الحلقات (loop-free code)، عبر إعادة التصريح عن الاسم باعتباره بنية (<code>‎struct‎</code>) غير مكتملة، كما هو الحال في <code>‎struct result;‎</code> أعلاه، لكن هذا المنظور سيئ ويستبعد أن يفهمها المبرمجون الآخرون؛ أيضًا، قد يكون التشخيص مربكًا.
</p>

<p>
	باختصار، أتاح دعم لغة C++‎ والمكتبة القياسية للنقل تحسينات جذرية على تعقيد الخوارزمية، ولكن بسبب عدم اكتمال الدعم، فإنّ تلك الفائدة ستكون على حساب التخلي عن ضمانات صحّة ووضوح الشيفرة التي يمكن أن توفّرها <code>‎const‎</code>.
</p>

<p>
	كتتمّة للمثال السابق، سنستخدَم صنف المتجه لقياس عدد عمليات نسخ العناصر الناجمة عن استدعاءات منشئ النسخ:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9527_13" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Item</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Copy_tracking_vector</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> n_copy_ops</span><span class="pun">()</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&amp;{</span><span class="pln">
                </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> value</span><span class="pun">;</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> value</span><span class="pun">;</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">

        </span><span class="typ">vector</span><span class="pun">&lt;</span><span class="typ">Item</span><span class="pun">&gt;</span><span class="pln"> items_</span><span class="pun">;</span><span class="pln">

        </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> n</span><span class="pun">()</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> n_copy_ops</span><span class="pun">();</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> push_back</span><span class="pun">(</span><span class="pln"> </span><span class="typ">Item</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> o </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> items_</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln"> o </span><span class="pun">);</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> begin</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> items_</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">();</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> end</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> items_</span><span class="pun">.</span><span class="pln">end</span><span class="pun">();</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
    </span><span class="typ">Copy_tracking_vector</span><span class="pun">(){}</span><span class="pln">
    </span><span class="typ">Copy_tracking_vector</span><span class="pun">(</span><span class="pln"> </span><span class="typ">Copy_tracking_vector</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> other </span><span class="pun">)</span><span class="pln">  </span><span class="pun">:</span><span class="pln"> items_</span><span class="pun">(</span><span class="pln"> other</span><span class="pun">.</span><span class="pln">items_ </span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln"> n_copy_ops</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> items_</span><span class="pun">.</span><span class="pln">size</span><span class="pun">();</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
    </span><span class="typ">Copy_tracking_vector</span><span class="pun">(</span><span class="pln"> </span><span class="typ">Copy_tracking_vector</span><span class="pun">&amp;&amp;</span><span class="pln"> other </span><span class="pun">)</span><span class="pln">  </span><span class="pun">:</span><span class="pln"> items_</span><span class="pun">(</span><span class="pln"> move</span><span class="pun">(</span><span class="pln"> other</span><span class="pun">.</span><span class="pln">items_ </span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{}</span><span class="pln">

    </span><span class="pun">};</span></pre>

<h2>
	منشئ النقل (Move constructor)
</h2>

<p>
	لنقل أن لدينا الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9527_15" style="">
<span class="kwd">class</span><span class="pln"> A
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">

    A</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> A </span><span class="pun">&amp;</span><span class="pln">other</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">this</span><span class="pun">-&gt;</span><span class="pln">a </span><span class="pun">=</span><span class="pln"> other</span><span class="pun">.</span><span class="pln">a</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">this</span><span class="pun">-&gt;</span><span class="pln">b </span><span class="pun">=</span><span class="pln"> other</span><span class="pun">.</span><span class="pln">b</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	الطريقة العادية لإنشاء منشئ نسخ هي باختيار الصيغة الموضحة أعلاه، وسيكون لدينا مُنشئ للصنف <code>A</code> يأخُذ مرجعًا إلى كائن آخر من النوع <code>A</code>، وينسخ الكائن يدويا داخل التابع.
</p>

<p>
	وبدلًا من ذلك، يمكننا كتابة <code>‎A(const A &amp;) = default;‎</code>، التي تنسخ تلقائيًا جميع الأعضاء باستخدام مُنشئ النسخ الخاص بها.
</p>

<p>
	سنأخذ مرجعًا يمينيًا بدلًا من اليساري، من أجل إنشاء مُنشئ نقل (move constructor)، كما هو مُوضّح هنا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9527_17" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Wallet</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> nrOfDollars</span><span class="pun">;</span><span class="pln">

    </span><span class="typ">Wallet</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">    </span><span class="com">//default ctor</span><span class="pln">
    </span><span class="typ">Wallet</span><span class="pun">(</span><span class="typ">Wallet</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln">other</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">this</span><span class="pun">-&gt;</span><span class="pln">nrOfDollars </span><span class="pun">=</span><span class="pln"> other</span><span class="pun">.</span><span class="pln">nrOfDollars</span><span class="pun">;</span><span class="pln">
        other</span><span class="pun">.</span><span class="pln">nrOfDollars </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	يرجى ملاحظة أنّنا ضبطنا القيم القديمة عند القيمة <code>‎zero‎</code>، ينسخ مُنشئ النقل الافتراضي (<code>‎Wallet(Wallet&amp;&amp;) = default;‎</code>) قيمة <code>‎nrOfDollars‎</code>، لأنّه نوع بيانات قديم (Plain Old Data أو POD).
</p>

<p>
	وبما أن دلالات النقل مُصمّمة للسماح بسرقة الحالة من النُسخة الأصلية، فالسؤال الآن هو كيف ستظهر النسخة الأصلية بعد تلك "السرقة"؟
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9527_19" style="">
<span class="typ">Wallet</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">
a</span><span class="pun">.</span><span class="pln">nrOfDollars </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Wallet</span><span class="pln"> b</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">a</span><span class="pun">));</span><span class="pln">    </span><span class="com">// B(B&amp;&amp; other); استدعاء</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">nrOfDollars </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">    </span><span class="com">//0</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">nrOfDollars </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">    </span><span class="com">//1</span></pre>

<p>
	وهكذا نكون قد أنشأنا كائنًا بشكل نقليّ (move constructed) من كائن آخر قديم. ربما يكون المثال السابق بسيطًا إلّا أنّه يوضّح آلية عمل مُنشئات النقل، وتظهر فائدته في الحالات الأكثر تعقيدًا، كما يحدث في حالات إدارة الموارد. انظر الشيفرة التالية التي تدير عمليات تتضمن نوعًا بعينه، وتملك مساعِدًا على الكومة (heap) وآخر في ذاكرتها، في المكدَّس غالبًا. وكلا المساعدان <code>DefaultConstructible</code> و <code>CopyConstructible</code> و <code>MoveConstructible</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9527_21" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">template</span><span class="str">&lt;typename&gt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">HeapHelper</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">template</span><span class="str">&lt;typename&gt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">StackHelper</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">OperationsManager</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> </span><span class="typ">MyType</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">OperationsManager</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> </span><span class="typ">HeapHelper</span><span class="pun">,</span><span class="pln"> </span><span class="typ">StackHelper</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
        </span><span class="typ">HeapHelper</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln">h_helper</span><span class="pun">;</span><span class="pln">
        </span><span class="typ">StackHelper</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> s_helper</span><span class="pun">;</span><span class="pln">
        </span><span class="com">// ...</span><span class="pln">
        </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
            </span><span class="com">// Five لـ &amp;Rule المنشئ الافتراضي</span><span class="pln">
            </span><span class="typ">OperationsManager</span><span class="pun">():</span><span class="pln"> h_helper</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">HeapHelper</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> T</span><span class="pun">&gt;)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

        </span><span class="typ">OperationsManager</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">MyType</span><span class="pun">&amp;</span><span class="pln"> other</span><span class="pun">):</span><span class="pln"> h_helper</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">HeapHelper</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(*</span><span class="pln">other</span><span class="pun">.</span><span class="pln">h_helper</span><span class="pun">)),</span><span class="pln"> s_helper</span><span class="pun">(</span><span class="pln">other</span><span class="pun">.</span><span class="pln">s_helper</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

        </span><span class="typ">MyType</span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">=(</span><span class="typ">MyType</span><span class="pln"> copy</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            swap</span><span class="pun">(*</span><span class="kwd">this</span><span class="pun">,</span><span class="pln"> copy</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}~</span><span class="typ">OperationsManager</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">h_helper</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">delete</span><span class="pln"> h_helper</span><span class="pun">;</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span></pre>

<p>
	منشئ نقل بدون <code>()swap</code>، يأخذ <code>*&lt;HeapHelper&lt;T</code> و <code>&lt;StackHelper &lt;T</code> من <code>other</code> من خلال فرض استخدام منشئ النقل الخاص بـ <code>&lt;StackHelper &lt;T</code>. ويٌحِلّ <code>nullptr</code> مكان <code>*&lt;HeapHelper&lt;T</code> الخاص بـ <code>other</code>، لمنع الأخير من حذف مساعِدنا الجديد حين يُدمَّر، نتابع المثال …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9527_23" style="">
<span class="pln">        </span><span class="typ">OperationsManager</span><span class="pun">(</span><span class="typ">MyType</span><span class="pun">&amp;&amp;</span><span class="pln"> other</span><span class="pun">)</span><span class="pln"> noexcept</span><span class="pun">:</span><span class="pln"> h_helper</span><span class="pun">(</span><span class="pln">other</span><span class="pun">.</span><span class="pln">h_helper</span><span class="pun">),</span><span class="pln">
            s_helper</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">other</span><span class="pun">.</span><span class="pln">s_helper</span><span class="pun">))</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                other</span><span class="pun">.</span><span class="pln">h_helper </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">nullptr</span><span class="pun">;</span><span class="pln">
            </span><span class="pun">}</span></pre>

<p>
	منشئ نقل (مع <code>()swap</code>)، نضع أعضاءنا في الشرط الذي نريد أن يكون فيه <code>other</code> ثم نبادل الأعضاء معه، نتابع …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9527_25" style="">
<span class="pln">        </span><span class="com">// OperationsManager(MyType&amp;&amp; other) noexcept : h_helper(nullptr) {</span><span class="pln">
        </span><span class="com">//       swap(*this, other);</span><span class="pln">
        </span><span class="com">// }</span><span class="pln">

        </span><span class="com">// Copy/move helper.</span><span class="pln">
        </span><span class="kwd">friend</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> swap</span><span class="pun">(</span><span class="typ">MyType</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">left</span><span class="pun">,</span><span class="pln"> </span><span class="typ">MyType</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">right</span><span class="pun">)</span><span class="pln"> noexcept
        </span><span class="pun">{</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">swap</span><span class="pun">(</span><span class="pln">left</span><span class="pun">.</span><span class="pln">h_helper</span><span class="pun">,</span><span class="pln"> right</span><span class="pun">.</span><span class="pln">h_helper</span><span class="pun">);</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">swap</span><span class="pun">(</span><span class="pln">left</span><span class="pun">.</span><span class="pln">s_helper</span><span class="pun">,</span><span class="pln"> right</span><span class="pun">.</span><span class="pln">s_helper</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span></pre>

<h2>
	إعادة استخدام كائن منقول
</h2>

<p>
	يمكنك إعادة استخدام كائن منقول على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9527_27" style="">
<span class="kwd">void</span><span class="pln"> consumingFunction</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> vec</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// بعض العمليات</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// 1, 2, 3, 4 تهيئة المتجه بالقيم</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> vec
    </span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
    </span><span class="com">// by move إرسال المتجه بالنقل</span><span class="pln">
    consumingFunction</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">vec</span><span class="pun">));</span><span class="pln">
    </span><span class="com">// في حالة غير محدّدة vec الكائن</span><span class="pln">
    </span><span class="com">// نظرا لأنّ الكائن لم يُدمَّر، يمكننا أن نسند إليه محتوى جديدا</span><span class="pln">
    </span><span class="com">// في هذه الحالة، سنسند قيمة فارغة إلى المتجه ما يجعله فارغًا </span><span class="pln">
    vec </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
    </span><span class="com">// نظرًا لأنّ المتجه قد اكتسب قيمة محدّدة، فيمكننا استخدامه بشكل طبيعي</span><span class="pln">
    vec</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="lit">42</span><span class="pun">);</span><span class="pln">
    </span><span class="com">// إرسال المتجه عبر النقل مجددا</span><span class="pln">
    consumingFunction</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">vec</span><span class="pun">));</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	إسناد النقل (Move assignment)
</h2>

<p>
	على غرار إسناد قيمة لكائن باستخدام <a data-ss1617022792="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-40-%D9%81%D8%A6%D8%A7%D8%AA-%D8%A7%D9%84%D9%82%D9%8A%D9%85-value-categories-%D9%81%D9%8A-cpp-r969/" rel="">مرجع يساري</a>، ثمّ نسخه، يمكننا أيضًا نقل القيم من كائن إلى آخر دون إنشاء كائن جديد، إذ نستدعي إسناد النقل، ثمّ ننقل القيم من كائن إلى كائن آخر موجود.
</p>

<p>
	سيتعيّن علينا أن <a data-ss1617022792="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-23-%D8%A7%D9%84%D8%AA%D8%AD%D9%85%D9%8A%D9%84-%D8%A7%D9%84%D8%B2%D8%A7%D8%A6%D8%AF-%D9%84%D9%84%D8%B9%D9%88%D8%A7%D9%85%D9%84-operator-overloading-%D9%81%D9%8A-cpp-r935/" rel="">نزيد تحميل</a> العامل <code>‎operator =‎</code> لنجعله يأخذ مرجعًا يمينيًا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9527_29" style="">
<span class="kwd">class</span><span class="pln"> A
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">
    A</span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">=(</span><span class="pln">A</span><span class="pun">&amp;&amp;</span><span class="pln"> other</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">this</span><span class="pun">-&gt;</span><span class="pln">a </span><span class="pun">=</span><span class="pln"> other</span><span class="pun">.</span><span class="pln">a</span><span class="pun">;</span><span class="pln">
        other</span><span class="pun">.</span><span class="pln">a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	هذه هي الصيغة النموذجية لتعريف إسناد النقل، إذ نزيد تحميل<code>‎operator =‎</code> حتى نتمكن من تزويده بمرجع يميني، وإسناده إلى كائن آخر.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9527_31" style="">
<span class="pln">A a</span><span class="pun">;</span><span class="pln">
a</span><span class="pun">.</span><span class="pln">a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
A b</span><span class="pun">;</span><span class="pln">
b </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">a</span><span class="pun">);</span><span class="pln">    </span><span class="com">// A&amp; operator= (A&amp;&amp; other) استدعاء</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">a </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">    </span><span class="com">//0</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">a </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">    </span><span class="com">//1</span></pre>

<p>
	ومن ثم يمكننا إسناد كائن نقليًا (move assign) إلى كائن لآخر.
</p>

<h2>
	استخدام دلالات النقل على الحاويات
</h2>

<p>
	يمكنك نقل حاوية بدلاً من نسخها على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9527_33" style="">
<span class="kwd">void</span><span class="pln"> print</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pun">&amp;</span><span class="pln"> vec</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pun">&amp;&amp;</span><span class="pln"> val</span><span class="pun">:</span><span class="pln"> vec</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> val </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", "</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// 1, 2, 3, 4 بالقيم vec1 تهيئة المتجه</span><span class="pln">
   </span><span class="com">// كمتجه فارغ vec2 ثمّ تهيئة</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> vec1
    </span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> vec2</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// 1, 2, 3, 4 السطر التالي سيطبع</span><span class="pln">
    print</span><span class="pun">(</span><span class="pln">vec1</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// السطر التالي سيطبع سطرا جديدا</span><span class="pln">
    print</span><span class="pun">(</span><span class="pln">vec2</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// عبر إسناد النقل vec2 أُسنِدت قيمة المتجه</span><span class="pln">
    </span><span class="com">// دون نسخها vec1 هذا سيسرق قيمة</span><span class="pln">

    vec2 </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">vec1</span><span class="pun">);</span><span class="pln">
    </span><span class="com">// هنا في حالة غير محدّدة، لكن يبقى صالحًا vec1 المتجه</span><span class="pln">
    </span><span class="com">// لم يُدمَّر بعد، لكن لا يوجد ضمان بخصوص الكائنات التي يحتويها vec1 الكائن</span><span class="pln">

    </span><span class="com">// 1, 2, 3, 4 السطر التالي سيطبع</span><span class="pln">
    print</span><span class="pun">(</span><span class="pln">vec2</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617022792="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 106: Move Semantics من كتاب <a data-ss1617022792="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">1023</guid><pubDate>Fri, 16 Oct 2020 13:04:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x633;&#x644;&#x648;&#x643; &#x63A;&#x64A;&#x631; &#x627;&#x644;&#x645;&#x639;&#x631;&#x641; Undefined Behavior &#x648;&#x627;&#x644;&#x633;&#x644;&#x648;&#x643; &#x63A;&#x64A;&#x631; &#x627;&#x644;&#x645;&#x62D;&#x62F;&#x62F; Unspeci&#xFB01;ed behavior &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%B3%D9%84%D9%88%D9%83-%D8%BA%D9%8A%D8%B1-%D8%A7%D9%84%D9%85%D8%B9%D8%B1%D9%81-undefined-behavior-%D9%88%D8%A7%D9%84%D8%B3%D9%84%D9%88%D9%83-%D8%BA%D9%8A%D8%B1-%D8%A7%D9%84%D9%85%D8%AD%D8%AF%D8%AF-unspeci%EF%AC%81ed-behavior-%D9%81%D9%8A-cpp-r1022/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_03/47.png.455a951ff5b0b2df55834cfd99227403.png" /></p>

<p>
	ما المقصود بالسلوك غير المعرَّف (undeﬁned behavior أو UB)؟ وفقًا لمعيار ISO C++‎ (الفقرة 1.3.24، N4296)، فهو:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		"أيّ سلوك لا يكون مفروضًا من قبل المواصفة القياسية الدولية."
	</p>
</blockquote>

<p>
	هذا يعني أنّه عندما يواجه البرنامج سلوكًا غير معرَّف، فإنّه يُسمَح له بفعل ما يريد. هذا قد يعني غالبًا التوقف عنا العمل، ولكنّه قد يعني تجاهله وعدم فعل أيّ شيء، أو قد يعمل البرنامج بشكل صحيح!، ولا شك أن عليك تجنب كتابة شيفرات تؤدي إلى سلوكيات غير معرَّفة.
</p>

<p>
	أما السلوك غير المُحدَّد فهو أيّ سلوك قد يتغير من جهاز إلى آخر، أو من مصرّف إلى آخر. لا يمكن التنبؤ الدقيق بسلوكيات البرامج التي تحتوي سلوكات غير محدّدة في مرحلة الاختبار، لأنّها تتعلق بالتقديم (implementation). لذا يُفضّل عموما تجنّب هذا النوع من السلوكات قدر الإمكان.
</p>

<h2>
	القراءة أو الكتابة من مؤشّر فارغ
</h2>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_7" style="">
<span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">ptr </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">nullptr</span><span class="pun">;</span><span class="pln">
</span><span class="pun">*</span><span class="pln">ptr </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">    </span><span class="com">// سلوك غير معرَّف</span></pre>

<p>
	هذا سلوك غير معرَّف لأنّ المؤشّر الفارغ لا يشير إلى أي كائن صالح، لذلك لا يوجد كائن في <code>‎*ptr‎</code> للكتابة عليه. ورغم أنّ هذا قد يتسبب غالبًا في حدوث خطأ في التجزئة (segmentation fault)، إلا أنّه غير مُعرَّف، وقد يحدث أي شيء.
</p>

<h2>
	استخدام متغيّر محلي غير مهيّأ
</h2>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_9" style="">
<span class="typ">int</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">    </span><span class="com">// سلوك غير معرَّف</span></pre>

<p>
	ينتج عن هذا سلوك غير معرَّف لأنّ <code>‎a‎</code> غير مهيّأة. يدّعي البعض (خطأً) أنّ هذا ناتج عن أنّ القيمة "غير معرَّفة "، أو بسبب "القيمة التي كانت سابقًا في ذلك الموقع من الذاكرة". والصحيح أنّ محاولة الوصول إلى قيمة <code>‎a‎</code> في المثال أعلاه هي التي أدّت إلى سلوك غير معرَّف.
</p>

<p>
	ومحاولة طباعة "قيمة مُهملة" (garbage value) هي عرض شائع في هذه الحالة لكن هذا ليس سوى شكل واحد ممكن من السلوكات غير المعرَّفة.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 14</strong>
</p>

<p>
	استخدام قيمة غير معرَّفة من نوع <code>‎unsigned char‎</code> لا ينتج عنه سلوك غير معرَّف عند استخدام القيمة كـ: *معامل ثاني أو ثالث للمعامل الشرطي الثلاثي (ternary conditional operator).
</p>

<ul>
<li>
		معامَل أيمن لمُعامل الفاصلة المُضمّن (comma operator).
	</li>
	<li>
		معامَل التحويل إلى <code>‎unsigned char‎</code>.
	</li>
	<li>
		معامَل أيمن لمُعامل الإسناد إذا كان المعامل الأيسر من النوع <code>‎unsigned char‎</code>.
	</li>
	<li>
		مُهيئ لكائن <code>‎unsigned char‎</code>؛
	</li>
</ul>
<p>
	أو حتى عند تجاهل القيمة. ففي مثل هذه الحالات، تنتشر (propagates) القيمة غير المعرَّفة ببساطة إلى نتيجة التعبير إن أمكن. لاحظ أنّ المتغيّرات الساكنة (<code>‎static‎</code>) تُهيّأ دائمًا عند القيمة صفر (إن أمكن):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_11" style="">
<span class="kwd">static</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">    </span><span class="com">// تساوي 0 'a' سلوك معرَّف، و</span></pre>

<h2>
	محاولة الوصول إلى فهرس خارج النطاق
</h2>

<p>
	محاولة الوصول إلى فهرس خارج نطاق مصفوفة (أو حاوية من المكتبة القياسية، إذ أنّها جميعًا منفَّذة باستخدام مصفوفات خام) تؤدّي إلى سلوك غير معرَّف:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_13" style="">
<span class="typ">int</span><span class="pln"> array</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
array</span><span class="pun">[</span><span class="lit">5</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">    </span><span class="com">// سلوك غير معرَّف</span></pre>

<p>
	لكن يُسمح بالحصول على مؤشّر يشير إلى نهاية المصفوفة (أي <code>‎array + 5‎</code> في هذه الحالة)، بيْد أنّه يُحظر تحصيله (dereference)، لأنّه ليس عنصرًا صالحًا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_15" style="">
<span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">end </span><span class="pun">=</span><span class="pln"> array </span><span class="pun">+</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">    </span><span class="com">// مؤشر إلى الموضع الذي يلي العنصر الأخير</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p </span><span class="pun">=</span><span class="pln"> array</span><span class="pun">;</span><span class="pln"> p </span><span class="pun">!=</span><span class="pln"> end</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">p</span><span class="pun">)</span><span class="pln">
    </span><span class="com">// `p` افعل شيئا ما بـ</span></pre>

<p>
	بشكل عام، لا يُسمح لك بإنشاء مؤشّر خارج الحدود، إذ يجب أن يشير المؤشّر إلى عنصر داخل المصفوفة، أو إلى الموضع الذي يلي نهاية المصفوفة.
</p>

<h2>
	حذف كائن مشتق عبر مؤشّر يشير إلى صنف أساسي لا يتوفّر على حاذِف وهمي
</h2>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_17" style="">
<span class="kwd">class</span><span class="pln"> base </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> derived</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> base </span><span class="pun">{};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    base</span><span class="pun">*</span><span class="pln"> p </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> derived</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">delete</span><span class="pln"> p</span><span class="pun">;</span><span class="pln">    </span><span class="com">// سلوك غير معرَّف</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تشير الفقرة ‎‎5.3.5 / 3‎‎ من المعيار إلى أنّه إذا استُدعِيت <code>‎delete‎</code> على كائن لا يحتوي نوعُه الساكن (static type) على مُدمّر وهمي (<code>‎virtual‎</code>)، فإنّه:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		إذا كان النوع الساكن للكائن المراد حذفه مختلفًا عن نوعه الديناميكي، فينبغي أن يكون النوع الساكن صنفًا أساسيًا للنوع الديناميكي للعنصر المراد حذفه، ويجب أن يكون للنوع الساكن مدمّر افتراضي، وإلّا فإنّ السلوك سيكون غير معرَّف.
	</p>
</blockquote>

<p>
	هذا يبقى صحيحًا بغض النظر عمّا إذا كان الصنف المشتق قد أضاف أو لم يضف أيّ حقول إلى الصنف الأساسي.
</p>

<h2>
	توسيع فضاءي الاسم "std" أو "posix"
</h2>

<p>
	يحظر المعيار (‎‎17.6.4.2.1 / 1) عمومًا توسيع فضاء الاسم <code>‎std‎</code>:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		يكون سلوك برامج C++‎ غير معرَّف عند إضافة تصريحات أو تعريفات إلى فضاء الاسم <code>std</code>، أو إلى فضاء اسم داخل <code>std</code>، ما لم يُحدّد خلاف ذلك.
	</p>
</blockquote>

<p>
	وينطبق نفس الشيء على<code>‎‎</code>‎posix‎‏ (‎‎17.6.4.2.2 / 1):
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		يكون سلوك برامج C++‎ غير معرَّف عند إضافة تصريحات أو تعريفات إلى فضاء الاسم <code>posix</code> أو إلى فضاء اسم ضمن <code>posix</code>، ما لم يُحدّد خلاف ذلك. انظر:
	</p>
</blockquote>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_19" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;algorithm&gt;</span><span class="pln">

</span><span class="kwd">namespace</span><span class="pln"> std
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لا شيء في المعيار يحظر على <code>‎algorithm‎</code> (أو أيٍّ من الترويسات التي يتضمّنها) إعادة تعريف نفس التعريف، وهذا قد يؤدّي إلى انتهاك قاعدة التعريف الواحد (One Deﬁnition Rule). ولذلك فهو ممنوع بشكل عام لكن مع بعض الاستثناءات، فمثلًا يُسمح بإضافة تخصيصات للأنواع المُعرَّفة من المستخدمين.
</p>

<p>
	في المثال التالي، لنفترض أنّ الشيفرة تحتوي على:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_21" style="">
<span class="kwd">class</span><span class="pln"> foo
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// شيفرة هنا</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	الشيفرة التالية صالحة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_23" style="">
<span class="kwd">namespace</span><span class="pln"> std
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">struct</span><span class="pln"> hash </span><span class="pun">&lt;</span><span class="pln"> foo</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">public</span><span class="pun">:</span><span class="pln"> </span><span class="typ">size_t</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">()(</span><span class="kwd">const</span><span class="pln"> foo </span><span class="pun">&amp;</span><span class="pln">f</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">};</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	حسابيات غير صالحة على المؤشّرات Invalid pointer arithmetic
</h2>

<p>
	ستتسبّب الاستخدامات التالية لحسابيات المؤشّر في حدوث سلوك غير معرَّف:
</p>

<ul>
<li>
		إضافة أو طرح عدد صحيح إذا لم تنتمي النتيجة إلى نفس المصفوفة التي يشير إليها المؤشّر. (هنا، يُعدّ العنصر الموجود بعد النهاية جزءًا من المصفوفة.)
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_25" style="">
<span class="typ">int</span><span class="pln"> a</span><span class="pun">[</span><span class="lit">10</span><span class="pun">];</span><span class="pln">
</span><span class="typ">int</span><span class="pun">*</span><span class="pln"> p1 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">a</span><span class="pun">[</span><span class="lit">5</span><span class="pun">];</span><span class="pln">
</span><span class="typ">int</span><span class="pun">*</span><span class="pln"> p2 </span><span class="pun">=</span><span class="pln"> p1 </span><span class="pun">+</span><span class="pln"> </span><span class="lit">4</span><span class="pun">;</span><span class="pln">    </span><span class="com">//  a[9] يشير إلى p2 جيد، لأنّ</span><span class="pln">
</span><span class="typ">int</span><span class="pun">*</span><span class="pln"> p3 </span><span class="pun">=</span><span class="pln"> p1 </span><span class="pun">+</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">    </span><span class="com">// a يشير إلى الموضع الذي يلي p2 جيد، لأنّ</span><span class="pln">
</span><span class="typ">int</span><span class="pun">*</span><span class="pln"> p4 </span><span class="pun">=</span><span class="pln"> p1 </span><span class="pun">+</span><span class="pln"> </span><span class="lit">6</span><span class="pun">;</span><span class="pln">    </span><span class="com">// سلوك غير معرَّف</span><span class="pln">
</span><span class="typ">int</span><span class="pun">*</span><span class="pln"> p5 </span><span class="pun">=</span><span class="pln"> p1 </span><span class="pun">-</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">    </span><span class="com">// a[0] يشير إلى p2 جيد، لأنّ</span><span class="pln">
</span><span class="typ">int</span><span class="pun">*</span><span class="pln"> p6 </span><span class="pun">=</span><span class="pln"> p1 </span><span class="pun">-</span><span class="pln"> </span><span class="lit">6</span><span class="pun">;</span><span class="pln">    </span><span class="com">// سلوك غير معرَّف</span><span class="pln">
</span><span class="typ">int</span><span class="pun">*</span><span class="pln">  p7 </span><span class="pun">=</span><span class="pln"> p3 </span><span class="pun">-</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">    </span><span class="com">// a[5] يشير إلى p7 جيد، لأنّ</span></pre>

<ul>
<li>
		طرح (subtraction) مؤشّرين إذا لم ينتمي كلاهما إلى نفس المصفوفة، مرّة أخرى، يعدّ العنصر الذي يلي العنصر الأخير من المصفوفة جزءًا من المصفوفة، والاستثناء الوحيد هو أنّه يمكن طرح مؤشّرين فارغين، والنتيجة ستكون 0.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_27" style="">
<span class="typ">int</span><span class="pln"> a</span><span class="pun">[</span><span class="lit">10</span><span class="pun">];</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> b</span><span class="pun">[</span><span class="lit">10</span><span class="pun">];</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p1 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">a</span><span class="pun">[</span><span class="lit">8</span><span class="pun">],</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p2 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">a</span><span class="pun">[</span><span class="lit">3</span><span class="pun">];</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> d1 </span><span class="pun">=</span><span class="pln"> p1 </span><span class="pun">-</span><span class="pln"> p2</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 5</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p3 </span><span class="pun">=</span><span class="pln"> p1 </span><span class="pun">+</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">  </span><span class="com">//  a يشير إلى الموضع الذي يلي العنصر الأخير في p2 جيد، لأنّ</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> d2 </span><span class="pun">=</span><span class="pln"> p3 </span><span class="pun">-</span><span class="pln"> p2</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 7</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p4 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">b</span><span class="pun">[</span><span class="lit">0</span><span class="pun">];</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> d3 </span><span class="pun">=</span><span class="pln"> p4 </span><span class="pun">-</span><span class="pln"> p1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// سلوك غير معرَّف</span></pre>

<ul>
<li>
		طرح مؤشّرين إذا كانت النتيجة تطفح (overﬂow) عن <code>‎std::ptrdiff_t‎</code>.
	</li>
	<li>
		أيّ عملية حسابية على المؤشّرات لا يتطابق فيها نوع أحد المعامَليْن (operand) مع النوعَ الديناميكي للكائن المُشار إليه من قبل ذلك المؤشّر (تجاهل التأهيل - cv-qualiﬁcation). فوفقًا للمعيار فإنه:
	</li>
</ul>
<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		"[بشكل خاص]، لا يمكن استخدام مؤشّر يشير إلى صنف أساسي في العمليات الحسابية للمؤشّرات عندما تحتوي المصفوفة على كائنات من نوع صنف مشتق."
	</p>
</blockquote>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_29" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> x</span><span class="pun">;</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Derived</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> y</span><span class="pun">;</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="typ">Derived</span><span class="pln"> a</span><span class="pun">[</span><span class="lit">10</span><span class="pun">];</span><span class="pln">
</span><span class="typ">Base</span><span class="pun">*</span><span class="pln"> p1 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">a</span><span class="pun">[</span><span class="lit">1</span><span class="pun">];</span><span class="pln">    </span><span class="com">// جيد</span><span class="pln">
</span><span class="typ">Base</span><span class="pun">*</span><span class="pln"> p2 </span><span class="pun">=</span><span class="pln"> p1 </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">    </span><span class="com">// Derived  يشير إلى p1 سلوك غير معرَّف، لأنّ</span><span class="pln">
</span><span class="typ">Base</span><span class="pun">*</span><span class="pln"> p3 </span><span class="pun">=</span><span class="pln"> p1 </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">    </span><span class="com">// نفس الشيء</span><span class="pln">
</span><span class="typ">Base</span><span class="pun">*</span><span class="pln"> p4 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">a</span><span class="pun">[</span><span class="lit">2</span><span class="pun">];</span><span class="pln">    </span><span class="com">// سلوك غير معرَّف</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> p5 </span><span class="pun">=</span><span class="pln"> p4 </span><span class="pun">-</span><span class="pln"> p1</span><span class="pun">;</span><span class="pln">    </span><span class="com">// Derived  يشيران إلى p4 و  p1  سلوك غير معرَّف، لأنّ</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Derived</span><span class="pun">*</span><span class="pln"> p6 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">a</span><span class="pun">[</span><span class="lit">1</span><span class="pun">];</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Derived</span><span class="pun">*</span><span class="pln"> p7 </span><span class="pun">=</span><span class="pln"> p6 </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">  </span><span class="com">// لا تهمّ cv-qualifiers جيد، لأن المؤهّلات </span></pre>

<h2>
	عدم وجود تعليمة return في دالّة نوعها المُعاد يخالف void
</h2>

<p>
	سيؤدّي حذف تعليمة <code>‎return‎</code> في دالّة نوعها المُعاد غير فارغ (<code>‎void‎</code>) إلى سلوك غير معرَّف.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_31" style="">
<span class="typ">int</span><span class="pln">
function</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// return غياب تعليمة </span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    function</span><span class="pun">();</span><span class="pln">    </span><span class="com">// سلوك غير معرَّف</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تطرح معظم المٌصرّفات الحديثة تحذيرًا في وقت التصريف إذا صادَفَت مثل هذه السلوكيات غير المعرَّفة.
</p>

<p>
	<strong>ملاحظة</strong>: <code>‎main‎</code> هي الاستثناء الوحيد لهذه القاعدة. إذا لم تحتو <code>‎main‎</code> على تعليمة <code>‎return‎</code>، فسيُدرِج المصرّف تلقائيًا التعبير <code>‎return 0;‎</code> نيابة عنك، لذلك يمكنك عدم وضعها إن شئت.
</p>

<h2>
	الوصول إلى مرجع معلّق (Accessing a dangling reference)
</h2>

<p>
	لا يمكن الوصول إلى مرجع يشير إلى كائن خرج عن النطاق أو تمّ تدميره، ويقال أن هذا المرجع "مُعلّق" (dangling)، لأنّه لم يُعد يشير إلى كائن صالح.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_33" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="typ">int</span><span class="pun">&amp;</span><span class="pln"> getX</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pun">&amp;</span><span class="pln"> r </span><span class="pun">=</span><span class="pln"> getX</span><span class="pun">();</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> r </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في هذا المثال، يخرج المتغيّر المحلي <code>‎x‎</code> عن النطاق عند إعادة <code>‎getX‎</code>. لاحظ أنّ تمديد دورة الحياة (lifetime extension) لا يمكنه أن يطيل دورة الحياة الخاصة بالمتغيّر المحلي بعد الخروج من نطاق الكتلة التي عُرِّف فيها. لذلك فإن المرجع <code>‎r‎</code> أصبح معلقًا. هذا البرنامج له سلوك غير معرَّف رغم أنّه قد يبدو أنّه يعمل بدون مشاكل، بل إنّه قد يطبع <code>‎42‎</code> في بعض الحالات.
</p>

<h2>
	قسمة عدد صحيح على الصفر
</h2>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_35" style="">
<span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">    </span><span class="com">// سلوك غير معرَّف</span></pre>

<p>
	القسمة على <code>‎0‎</code> هي عمليّة غير معرَّفة في الرياضيات، فلا جرم أنّها تؤدّي إلى سلوك غير معرَّف في البرمجة.
</p>

<p>
	في المثال التالي، <code>x</code> تساوي موجب ما لا نهاية <code>infinity+</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_37" style="">
<span class="typ">float</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5.0f</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">0.0f</span><span class="pun">;</span><span class="pln"> </span></pre>

<p>
	تعتمد معظم التنفيذات (implementaions) على المعيار IEEE-754، الذي ينصّ على أنّ قسمة عدد عشري (ﬂoating point) على الصفر ستعيد القيمة الخاصة <strong>"ليس عددًا"</strong> <code>‎NaN‎</code> (إذا كان البسْط يساوي <code>‎0.0f‎</code>)، أو <code>‎infinity‎</code> (إذا كان البسط موجبًا)، أو <code>‎-infinity‎</code> (إذا كان البسط سالباً).
</p>

<h2>
	الإزاحة بعدد غير صالح من المنازل
</h2>

<p>
	بالنسبة لعامل الإزاحة (shift operator) المُضمّن، يجب أن يكون العامل الأيمن غير سالب وأصغر من طول العامل الأيسر بالبتّات. خلاف ذلك، فإنّ السلوك سيكون غير معرَّف.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_39" style="">
<span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pun">;</span><span class="pln">    </span><span class="com">// سلوك غير معرَّف</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">    </span><span class="com">// ok</span></pre>

<p>
	في السطرين التاليين، ينتج لنا سلوك غير معرَّف إذا كان طول <code>int</code> يساوي 32 أو أقل …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_41" style="">
<span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> d </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">32</span><span class="pun">;</span><span class="pln">  
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> e </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">32</span><span class="pun">;</span></pre>

<p>
	في حالة <code>const int g = f &lt;&lt; 10</code>، هذا مقبول حتى لو كان طول <code>signed char</code> أقل من أو يساوي 10 بت، ويجب ألا يقل طول <code>int</code> عن 16 بت …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_43" style="">
<span class="kwd">const</span><span class="pln"> </span><span class="kwd">signed</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> f </span><span class="pun">=</span><span class="pln"> </span><span class="str">'x'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> g </span><span class="pun">=</span><span class="pln"> f </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln">   </span></pre>

<h2>
	تخصيص الذاكرة وتحريرها بشكل غير صحيح
</h2>

<ul>
<li>
		لا يمكن تحرير (deallocated) كائن عبر <code>‎delete‎</code> إلا إن كان قد خُصِّص من قبل عبر <code>‎new‎</code> ولم يكن مصفوفةً. أما إذا لم يكن الوسيط المُمرّر إلى <code>‎delete‎</code> مُعادًا من <code>‎new‎</code>، أو لم يكن مصفوفةً، فسيكون السلوك غير معرَّف.
	</li>
	<li>
		لا يمكن تحرير كائن عبر <code>‎delete[]‎</code> إلا إن كان قد خُصِّص من قبل عبر <code>‎new‎</code> ولم يكن مصفوفةً. أما إذا لم يكن الوسيط المُمرّر إلى <code>‎delete[]‎</code> مُعادًا من <code>‎new‎</code>، أو لم يكن مصفوفةً، فسيكون السلوك غير معرَّف.
	</li>
	<li>
		إذا لم يكن الوسيط المُمرّر إلى <code>‎free‎</code> مُعادًا من <code>‎malloc‎</code>، فسيكون السلوك غير معرَّف.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_45" style="">
<span class="typ">int</span><span class="pun">*</span><span class="pln"> p1 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">int</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">delete</span><span class="pln"> p1</span><span class="pun">;</span><span class="pln">    </span><span class="com">// صحيح</span><span class="pln">
</span><span class="com">// delete[] p1;    // غير معرَّف</span><span class="pln">
</span><span class="com">// free(p1);    //  غير معرَّف</span><span class="pln">
</span><span class="typ">int</span><span class="pun">*</span><span class="pln"> p2 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">int</span><span class="pun">[</span><span class="lit">10</span><span class="pun">];</span><span class="pln">
</span><span class="kwd">delete</span><span class="pun">[]</span><span class="pln"> p2</span><span class="pun">;</span><span class="pln">    </span><span class="com">// صحيح</span><span class="pln">
</span><span class="com">// delete p2;    //  غير معرَّف</span><span class="pln">
</span><span class="com">// free(p2);    //  غير معرَّف</span><span class="pln">
</span><span class="typ">int</span><span class="pun">*</span><span class="pln"> p3 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">*&gt;(</span><span class="pln">malloc</span><span class="pun">(</span><span class="kwd">sizeof</span><span class="pun">(</span><span class="typ">int</span><span class="pun">)));</span><span class="pln">
free</span><span class="pun">(</span><span class="pln">p3</span><span class="pun">);</span><span class="pln">    </span><span class="com">// صحيح</span><span class="pln">
</span><span class="com">// delete p3;    //  غير معرَّف</span><span class="pln">
</span><span class="com">// delete[] p3;    //  غير معرَّف</span></pre>

<p>
	يمكن تجنّب هذه المشاكل عن طريق تجنّب <code>‎malloc‎</code> و <code>‎free‎</code> في برامج C++‎، فمن الأفضل استخدام المؤشّرات الذكية بدلًا من <code>‎new‎</code> و <code>‎delete‎</code> الخام، كما يُفضَّل استخدام <code>‎std::vector‎</code> و <code>‎std::string‎</code> على <code>‎new‎</code> و <code>‎delete[]‎</code>
</p>

<h2>
	طفح الأعداد الصحيحة المُؤشّرة (Signed Integer Overﬂow)
</h2>

<p>
	انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_47" style="">
<span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> INT_MAX </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="com">// سلوك غير معرَّف</span></pre>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		إذا لم تُعرَّف النتيجة رياضيًا أثناء تقييم تعبير ما أو لم تكن ضمن نطاق القيم القابلة للتمثيل لنوع ذلك التعبير، فسيكون السلوك غير معرَّف. (C++‎ 11، الفقرة 5/4 من المعيار)
	</p>
</blockquote>

<p>
	هذا أحد أسوأ حالات السلوكيات غير المعرَّفة لأنّها تنتج سلوكًا غير معرَّف متكرّر ولا يوقف البرنامج، لذا قد لا ينتبه إليه المطوّرون.
</p>

<p>
	من ناحية أخرى:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_49" style="">
<span class="kwd">unsigned</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> UINT_MAX </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="com">// تساوي 0 x </span></pre>

<p>
	يؤدي هذا إلى سلوك معرَّف جيدًا بما أنه:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		يجب على الأعداد الصحيحة غير المُؤشّرة والمُصرّح عنها أن تلتزم بقوانين معامل الباقي الحسابي (arithmetic modulo)‏ <code>‎2^n‎</code>، حيث يمثّل <code>‎n‎</code> عدد البتات في تمثيل الأعداد الصحيحة.
	</p>
</blockquote>

<p>
	(C++‎ 11 الفقرة ‎‎3.9.1 / 4 من المعيار)
</p>

<p>
	أحيانًا قد تستغل المٌصرّفات السلوكات غير المعرَّفة وتحسّنها.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_51" style="">
<span class="kwd">signed</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x </span><span class="pun">&gt;</span><span class="pln"> x </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// افعل شيئا ما</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	وطالما أنّ طفح الأعداد الصحيحة المُؤشّرة (signed integer overﬂow) يؤدي إلى سلوك غير معرَّف، فيمكن للمُصرّف تجاهله وافتراض أنّه لن يحدث أبدا، ومن ثم يمكنه استبعاد كتلة <code>if</code>.
</p>

<h2>
	التعريفات المتعدّدة غير المتطابقة (قاعدة التعريف الواحد)
</h2>

<p>
	إذا كان أي مما يلي معرَّفًا في عدة واحدات ترجمة فيجب أن تكون جميع التعريفات متطابقة أو سيكون السلوك غير معرَّف وفقًا <a data-ss1617022794="1" href="https://en.wikipedia.org/wiki/One_Definition_Rule" rel="external nofollow">لقاعدة التعريف الواحد</a> (ODR): الأصناف، التعدادات، الدوال المضمنَّة، القوالب، الأعضاء في القوالب.
</p>

<p>
	<code>foo.h‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_53" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">double</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> y</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">Foo</span><span class="pln"> get_foo</span><span class="pun">();</span></pre>

<p>
	<code>‎‎foo.cpp</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_55" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">"foo.h"</span><span class="pln">

</span><span class="typ">Foo</span><span class="pln"> get_foo</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln"> </span><span class="com">/*التنفيذ*/</span><span class="pln"> </span><span class="pun">}</span></pre>

<p>
	<code>main.cpp</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_57" style="">
<span class="com">// Foo أريد الوصول إلى العضو الخاص، لذا سأستخدم النوع الخاص بي بدلًا من </span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">double</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> y</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">Foo</span><span class="pln"> get_foo</span><span class="pun">();</span><span class="pln">    </span><span class="com">// foo.h سنصرّح عن هذه الدالة بأنفسنا لأننا لم نُضمَِن</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Foo</span><span class="pln"> foo </span><span class="pun">=</span><span class="pln"> get_foo</span><span class="pun">();</span><span class="pln">
    </span><span class="com">// foo.y افعل شيئا ما بـ</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يتسبّب البرنامج أعلاه في سلوك غير معرَّف لأنّه يحتوي على تعريفين غير متطابقين للصنف <code>‎::Foo‎</code>، والذي له صلة خارجية (external linkage) في وحدات ترجمة مختلفة. وعلى عكس إعادة تعريف صنف داخل وحدة الترجمة نفسها، فإن المٌصرّف ليس مُلزمًا بتشخيص هذه المشكلة.
</p>

<h2>
	محاولة تعديل كائن ثابت (Modifying a const object)
</h2>

<p>
	إنّ أيّ محاولة لتعديل كائن ثابت <code>‎const‎</code> سينتج عنها سلوك غير معرَّف، هذا ينطبق على المتغيّرات الثابتة وأعضاء الكائنات الثابتة، وأعضاء الأصناف المُصرّح عنها عبر <code>‎const‎</code>. بالمقابل، فإنّ عضوا متغيّرًا <code>‎mutable‎</code> من كائن ثابت <code>‎const‎</code> لن يكون ثابتا، وقد تحدث هذه المحاولة عبر <code>‎const_cast‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_59" style="">
<span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">123</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const_cast</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">&amp;&gt;(</span><span class="pln">x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">456</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> x </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span></pre>

<p>
	عادة ما يُضمِّن المٌصرّف قيمة الكائن <code>‎const int‎</code>، وعليه فيحتمل أن تُصرَّف هذه الشيفرة وتطبع <code>‎123‎</code>، كذلك يمكن للمٌصرّفات وضع قيم الكائنات الثابتة في ذاكرة مخصّصة للقراءة فقط، ومن ثم قد يحدث خطأ في التجزئة (segmentation fault). وسيكون السلوك بشكل عام غير معرَّف، ولا يمكن التنبؤ بما سيفعله البرنامج.
</p>

<p>
	ينطوي البرنامج التالي على خطأ خفِىّ:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_61" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Foo</span><span class="pun">*</span><span class="pln"> instance</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> get_x</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> m_x</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">void</span><span class="pln"> set_x</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        m_x </span><span class="pun">=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Foo</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Foo</span><span class="pun">*</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">this_ref</span><span class="pun">):</span><span class="pln"> m_x</span><span class="pun">(</span><span class="pln">x</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            this_ref </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

    </span><span class="typ">int</span><span class="pln"> m_x</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">friend</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">getFoo</span><span class="pun">();</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">getFoo</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> foo</span><span class="pun">(</span><span class="lit">123</span><span class="pun">,</span><span class="pln"> instance</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> foo</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> do_evil</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    instance</span><span class="pun">-&gt;</span><span class="pln">set_x</span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">foo </span><span class="pun">=</span><span class="pln"> getFoo</span><span class="pun">();</span><span class="pln">
    do_evil</span><span class="pun">(</span><span class="lit">456</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> foo</span><span class="pun">.</span><span class="pln">get_x</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في الشيفرة السابقة، أنشأت دالة <code>‎getFoo‎</code> مفردة (singleton) من نوع <code>‎const Foo‎</code>، وتمت تهيئة عضوها <code>‎m_x‎</code> عند القيمة <code>‎123‎</code>. ثم استُدعِيت <code>‎do_evil‎</code> يبدو أنّ هذا غيّر قيمة <code>‎foo.m_x‎</code> إلى 456. فأين مكمن الخطأ؟
</p>

<p>
	لا تفعل <code>‎do_evil‎</code> أيّ شيء شرّير رغم اسمها، فكلّ ما تفعله هو استدعاء ضابط (setter) من خلال <code>‎Foo*‎</code>، لكنّ هذا المؤشّر يشير إلى كائن <code>‎const Foo‎</code> رغم عدم استخدام <code>‎const_cast‎</code>، وقد تمّ الحصول على هذا المؤشّر عبر مُنشئ <code>‎Foo‎</code>.
</p>

<p>
	لا يصبح كائن ثابت ثابتًا (<code>‎const‎</code>) حتى تكتمل عمليّة التهيئة، لذلك فإنّ نوع المؤشّر <code>‎this‎</code> يساوي <code>‎Foo*‎</code>، وليس <code>const Foo*‎</code> داخل المنشئ، وبسبب ذلك يحدث سلوك غير معرَّف، رغم عدم وجود أيّ إنشاءات خطيرة في هذا البرنامج.
</p>

<h2>
	محاولة إعادة قيمة من دالة لا تعيد قيمة
</h2>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	هذا مثال من المعيار [dcl.attr.noreturn]:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_63" style="">
<span class="pun">[[</span><span class="pln">noreturn</span><span class="pun">]]</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">throw</span><span class="pln"> </span><span class="str">"error"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// حسنا</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="pun">[</span><span class="pln">
    </span><span class="pun">[</span><span class="pln">noreturn</span><span class="pun">]</span><span class="pln">
    </span><span class="pun">]</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> q</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// السلوك غير معرَّف في حال كان الوسيط أصغر من أو يساوي 0</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">throw</span><span class="pln"> </span><span class="str">"positive"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span></pre>

<h2>
	تكرار لا نهائي للقالب
</h2>

<p>
	هذا مثال من المعيار ‎‎[temp.inst] / 17: يتطلب التوليد الضمني لـ <code>&lt;X&lt;T</code> استنساخًا ضمنيًا والذي يتطلب بدوره استنساخًا ضمنيًا لـ <code>&lt;*X&lt;T</code> والذي يتطلب بدوره استنساخًا ضمنيًا لـ <code>&lt;**X&lt;T</code> وهكذا …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_65" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> X
</span><span class="pun">{</span><span class="pln">
    X</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p</span><span class="pun">;</span><span class="pln">    </span><span class="com">// OK</span><span class="pln">
    X</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">*&gt;</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">  
</span><span class="pun">};</span></pre>

<h2>
	التدفق الزائد الناتج عن التحويل من وإلى عدد عشري
</h2>

<p>
	عند تحويل:
</p>

<ul>
<li>
		نوع عددي صحيح إلى نوع عدد عشري.
	</li>
	<li>
		أو نوع عدد عشري إلى نوع عددي صحيح.
	</li>
	<li>
		أو نوع نوع عدد عشري إلى نوع عدد عشري أقصر.
	</li>
</ul>
<p>
	فسيحدث سلوك غير معرَّف إن كانت القيمة المصدرية (source value) خارج نطاق القيم التي يمكن تمثيلها في النوع المقصود، انظر المثال التالي حيث لا يمكن لـ <code>int</code> تخزين عناصر كبيرة إلى هذا الحد، لذا يحدث سلوك غير معرَّف.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_67" style="">
<span class="kwd">double</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1e100</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> y </span><span class="pun">=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">    </span></pre>

<h2>
	تعديل سلسلة نصّية مجردة
</h2>

<p>
	<strong>الإصدار &lt; C++‎ 11</strong> <code>‎"hello world"‎</code> في المثال أدناه هي سلسلة نصّية مجردة، لذا فإنّ محاولة تعديلها ستؤدّي إلى سلوك غير معرَّف.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_69" style="">
<span class="kwd">char</span><span class="pln"> </span><span class="pun">*</span><span class="pln">str </span><span class="pun">=</span><span class="pln"> </span><span class="str">"hello world"</span><span class="pun">;</span><span class="pln">
str</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">'H'</span><span class="pun">;</span></pre>

<p>
	طريقة تهيئة <code>‎str‎</code> في المثال أعلاه أصبحت مهملة رسميًا في C++‎ 03 (من المقرر إزالتها من الإصدارات المستقبلية للمعيار)، قد تصدر بعض المٌصرّفات القديمة (قبل عام 2003) تحذيرًا بشأن ذلك، وأصبحت المٌصرّفات تحذّر عادة من أنّ هناك تحويلات متجاوَزة بعد عام 2003.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	المثال أعلاه غير جائز ويؤدّي إلى إطلاق عملية تشخيص (diagnostic) من قبل المصرّف في الإصدار C++‎ 11 والإصدارات الأحدث. يمكن إنشَاء مثال لتوضيح السلوك غير المعرَّف من خلال السماح بتحويل النوع بشكل صريح على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_71" style="">
<span class="kwd">char</span><span class="pln"> </span><span class="pun">*</span><span class="pln">str </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">const_cast</span><span class="pun">&lt;</span><span class="kwd">char</span><span class="pun">*&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="str">"hello world"</span><span class="pun">);</span><span class="pln">
str</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">'H'</span><span class="pun">;</span></pre>

<h2>
	الوصول إلى كائن بافتراض أنّه من النوع الخاطئ
</h2>

<p>
	لا تجوز محاولة الوصول إلى كائن من نوع معيّن كما لو كان من نوع آخر مختلف في معظم الحالات -متجاهلين المؤهِّلات cv- qualiﬁers. انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_73" style="">
<span class="typ">float</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> y </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">reinterpret_cast</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">&amp;&gt;(</span><span class="pln">x</span><span class="pun">);</span></pre>

<p>
	النتيجة ستكون سلوكًا غير معرَّف.
</p>

<p>
	هناك بعض الاستثناءات لقاعدة التسمية البديلة الصارمة (strict aliasing rule):
</p>

<ul>
<li>
		يمكن الوصول إلى كائن كما لو كان من صنف أساسي (base class) للصنف الفعلي الذي ينتمي إليه.
	</li>
	<li>
		يمكن الوصول إلى أيّ نوع كما لو كان من النوع <code>‎char‎</code> أو <code>‎unsigned char‎</code>، لكنّ العكس ليس صحيحًا، مثلًا: لا يمكن الوصول إلى مصفوفة مكوّنة من حروف كما لو كانت نوعًا عشوائيًا.
	</li>
	<li>
		يمكن الوصول إلى نوع عددي صحيح مؤشّر كما لو كان من النوع غير المؤشَّر المقابل له، والعكس صحيح.
	</li>
</ul>
<p>
	هناك قاعدة قريبة من هذا تقول أنّه إذا استُدعِي تابع غير ساكن على كائن من صنف آخر غير الصنف الذي عُرّف فيه ذلك التابع، أو صنف مشتقّ منه، فسيحدث سلوك غير معرَّف. ويبقى هذا صحيحًا حتى لو لم تحاول الدالّة الوصول إلى ذلك الكائن.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_75" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Derived</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Unrelated</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="typ">Unrelated</span><span class="pln"> u</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Derived</span><span class="pun">&amp;</span><span class="pln"> r1 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">reinterpret_cast</span><span class="pun">&lt;</span><span class="typ">Derived</span><span class="pun">&amp;&gt;(</span><span class="pln">u</span><span class="pun">);</span><span class="pln"> </span><span class="com">// ok</span><span class="pln">
r1</span><span class="pun">.</span><span class="pln">f</span><span class="pun">();</span><span class="pln"> </span><span class="com">//  سلوك غير معرَّف</span><span class="pln">
</span><span class="typ">Base</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Derived</span><span class="pun">&amp;</span><span class="pln"> r2 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">reinterpret_cast</span><span class="pun">&lt;</span><span class="typ">Derived</span><span class="pun">&amp;&gt;(</span><span class="pln">b</span><span class="pun">);</span><span class="pln"> </span><span class="com">// ok</span><span class="pln">
r2</span><span class="pun">.</span><span class="pln">f</span><span class="pun">();</span><span class="pln">   </span><span class="com">//  سلوك غير معرَّف</span></pre>

<h2>
	التحويلات غير الصالحة من صنف مشتق إلى صنف أساسي، للمؤشّرات العضوية (pointers to members)
</h2>

<p>
	عند استخدام <code>‎static_cast‎</code> لتحويل <code>‎T D::*‎</code> إلى <code>‎T B::*‎</code>، يجب أن ينتمي العضو المشار إليه إلى صنف يمثّل صنفًا أساسيًا (base class) أو مشتقًّا من <code>‎B‎</code>. بخلاف ذلك، فإنّ السلوك سيكون غير معرَّف.
</p>

<h2>
	محاولة تدمير كائن دُمِّر من قبل
</h2>

<p>
	في هذا المثال، يُستدعى المُدمّر بشكل صريح على كائن سيتم تدميره تلقائيًا في وقت لاحق.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_77" style="">
<span class="kwd">struct</span><span class="pln"> S
</span><span class="pun">{</span><span class="pln">
    </span><span class="pun">~</span><span class="pln">S</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"destroying S\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    S s</span><span class="pun">;</span><span class="pln">
    s</span><span class="pun">.~</span><span class="pln">S</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">    </span><span class="com">// سلوك غير معرَّف، بسبب تدمير العنصر للمرة الثانية هنا</span></pre>

<p>
	تحدث مشكلة مماثلة عندما يشير مؤشّر <code>‎std::unique_ptr&lt;T&gt;‎</code> إلى نوع <code>‎T‎</code> ذي مدّة تخزين (storage duration) تلقائية أو ساكنة، إذ يؤدي تدمير <code>s</code> في حال عودة <code>f</code> إلى سلوك غير معرَّف، لأن <code>s</code> مدمَّرة فعلًا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_79" style="">
<span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">unique_ptr</span><span class="pun">&lt;</span><span class="pln">S</span><span class="pun">&gt;</span><span class="pln"> p</span><span class="pun">);</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    S s</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">unique_ptr</span><span class="pun">&lt;</span><span class="pln">S</span><span class="pun">&gt;</span><span class="pln"> p</span><span class="pun">(&amp;</span><span class="pln">s</span><span class="pun">);</span><span class="pln">
    f</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">p</span><span class="pun">));</span><span class="pln"> 
</span><span class="pun">}</span></pre>

<p>
	محاولة تدمير كائن ما مرتين قد ينتج عنها وجود مؤشّرين مشتركين <code>‎shared_ptr‎</code> يديران الكائن دون مشاركة الملكية مع بعضهما البعض.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_81" style="">
<span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">shared_ptr</span><span class="pun">&lt;</span><span class="pln">S</span><span class="pun">&gt;</span><span class="pln"> p1</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">shared_ptr</span><span class="pun">&lt;</span><span class="pln">S</span><span class="pun">&gt;</span><span class="pln"> p2</span><span class="pun">);</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    S</span><span class="pun">*</span><span class="pln"> p </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> S</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// أريد تمرير نفس الكائن مرّتين</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">shared_ptr</span><span class="pun">&lt;</span><span class="pln">S</span><span class="pun">&gt;</span><span class="pln"> sp1</span><span class="pun">(</span><span class="pln">p</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">shared_ptr</span><span class="pun">&lt;</span><span class="pln">S</span><span class="pun">&gt;</span><span class="pln"> sp2</span><span class="pun">(</span><span class="pln">p</span><span class="pun">);</span><span class="pln">
    f</span><span class="pun">(</span><span class="pln">sp1</span><span class="pun">,</span><span class="pln"> sp2</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">           </span></pre>

<p>
	نتيجة الشيفرة السابقة سلوك غير معرف لأن <code>sp2</code> و <code>sp1</code> سيحاولان تدمير <code>s</code> بشكل منفصل، لكن بأي حال، فما يلي صحيح:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_85" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">shared_ptr</span><span class="pun">&lt;</span><span class="pln">S</span><span class="pun">&gt;</span><span class="pln"> sp</span><span class="pun">(</span><span class="pln">p</span><span class="pun">);</span><span class="pln">
f</span><span class="pun">(</span><span class="pln">sp</span><span class="pun">,</span><span class="pln"> sp</span><span class="pun">);</span></pre>

<h2>
	محاولة الوصول إلى عضو غير موجود عبر مؤشّر عضوي
</h2>

<p>
	عند محاولة الوصول إلى عضو غير ساكن من كائن معيّن عبر مؤشّر عضوي (pointer to member)، فسيحدث سلوك غير معرَّف إذا لم يكن الكائن يحتوي فعليًا ذلك العضو الذي يشير إليه المؤشّر، إذ يمكن الحصول على المؤشّر العضوي عبر <code>‎static_cast‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_87" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> x</span><span class="pun">;</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Derived</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> y</span><span class="pun">;</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="typ">Derived</span><span class="pun">::*</span><span class="pln">pdy </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="typ">Derived</span><span class="pun">::</span><span class="pln">y</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="typ">Base</span><span class="pun">::*</span><span class="pln">pby </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pln"> </span><span class="typ">Base</span><span class="pun">::*&gt;(</span><span class="pln">pdy</span><span class="pun">);</span><span class="pln">
</span><span class="typ">Base</span><span class="pun">*</span><span class="pln"> b1 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Derived</span><span class="pun">;</span><span class="pln">
b1</span><span class="pun">-&gt;*</span><span class="pln">pby </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">    </span><span class="com">// Derived  في كائن من النوع y جيد، تعيين</span><span class="pln">
</span><span class="typ">Base</span><span class="pun">*</span><span class="pln"> b2 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Base</span><span class="pun">;</span><span class="pln">
b2</span><span class="pun">-&gt;*</span><span class="pln">pby </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">    </span><span class="com">// Base في  y سلوك غير معرَّف، لأنّه لا يوجد عضو</span></pre>

<h2>
	تحويل غير صالح من الصنف الأساسي إلى صنف مشتق
</h2>

<p>
	عند استخدام <code>‎static_cast‎</code> على مؤشّر أو مرجع يشير إلى صنف أساسي، من أجل تحويله إلى مؤشّر أو مرجع يشير إلى صنف مشتق منه، فسيكون السلوك غير معرَّف إن لم يكن المُعامل يشير (يرجِع) إلى كائن من الصنف المشتق.
</p>

<h2>
	طفح الأعداد العشرية Floating point overflow
</h2>

<p>
	إذا أنتجت عملية حسابية قيمة لا تنتمي إلى مجال القيم التي يمكن تمثيلها في النوع الناتج، وكان يُفترض أن تعيد عددًا عشريًا، فإنّ السلوك سيكون غير معرَّف وفقًا لمعيار C++‎، لكن قد يكون معرَّفا في معايير أخرى قد تتوافق معها الآلة، مثل IEEE 754.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_89" style="">
<span class="typ">float</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1.0</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10000</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    x </span><span class="pun">*=</span><span class="pln"> </span><span class="lit">10.0</span><span class="pun">;</span><span class="pln">    </span><span class="com">// قد يؤدّي في النهاية إلى حدوث تدفق زائد، وسينتج عن ذلك سلوك غير معرَّف</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	استدعاء أعضاء وهمية (خالصة) من مُنشئ أو مدّمر
</h2>

<p>
	ينصّ <a data-ss1617022794="1" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4527.pdf" rel="external nofollow">المعيار (10.4)</a> على ما يلي:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		يمكن استدعاء التوابع من مُنشئ أو مُدمّر خاص بصنف مجرّد، وسيحدث سلوك معرَّف عند إجراء استدعاء وهمي - virtual call - ‏(10.3) لدالّة وهمية خالصة - pure virtual function - بشكل مباشر أو غير مباشر على الكائن الذي يجري إنشاءه (أو تدميره) من مثل هذا المُنشئ (أو المدمّر).
	</p>
</blockquote>

<p>
	وعمومًا، <a data-ss1617022794="1" href="https://www.artima.com/cppsource/nevercall.html" rel="external nofollow">يقترح</a> بعض كُبراء C++‎، مثل سكوت مايرز (Scott Meyers) تجنّب استدعاء الدوال الوهميّة (حتى غير الخالصة منها) من المنشئات والمُدمِّرات. انظر المثال التالي المُعدّل من الرابط أعلاه:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_91" style="">
<span class="kwd">class</span><span class="pln"> transaction
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        transaction</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            log_it</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> log_it</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> sell_transaction</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> transaction
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> log_it</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
    </span><span class="pun">{</span><span class="pln"> </span><span class="com">/* افعل شيئا ما */</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	لنفترض أنّنا أنشأنا كائنًا <code>‎sell_transaction‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_93" style="">
<span class="pln">sell_transaction s</span><span class="pun">;</span></pre>

<p>
	يستدعي هذا ضمنيًا مُنشئ <code>‎sell_transaction‎</code>، الذي يستدعي أولًا مُنشئ <code>‎transaction‎</code>. وفي لحظة استدعاء مُنشئ <code>‎transaction‎</code> لن يكون الكائن من النوع <code>‎sell_transaction‎</code> بعدُ وإنّما سيكون من النوع <code>‎transaction‎</code>. وعليه فإنّ استدعاء <code>‎log_it‎</code> في <code>‎transaction::transaction()‎</code> لن يقوم بالمُتوقّع منه - أي استدعاء <code>‎sell_transaction::log_it‎</code>.
</p>

<ul>
<li>
		إذا كانت <code>‎log_it‎</code> وهمية خالصة، كما هو مُوضّح في هذا المثال، فإنّ السلوك سيكون غير معرَّف
	</li>
	<li>
		إذا لم تكن <code>‎log_it‎</code> وهمية خالصة، فستُستدعى <code>‎transaction::log_it‎</code>.
	</li>
</ul>
<h2>
	استدعاء دالّة عبر مؤشّر دالّة من نوع غير مطابق
</h2>

<p>
	من أجل استدعاء دالة عبر مؤشّر دالة، يجب أن يتطابق نوع مؤشّر الدالّة مع نوع الدالّة، أما خلاف ذلك فإنّ السلوك سيكون غير معرَّف. هذا مثال على ذلك:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_96" style="">
<span class="typ">int</span><span class="pln"> f</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">void</span><span class="pun">(*</span><span class="pln">p</span><span class="pun">)()</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">reinterpret_cast</span><span class="pun">&lt;</span><span class="kwd">void</span><span class="pun">(*)()</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">f</span><span class="pun">);</span><span class="pln">
p</span><span class="pun">();</span><span class="pln">    </span><span class="com">// غير معرَّف</span></pre>

<h2>
	الإشارة إلى أعضاء غير ساكنة في قائمة مهيئ
</h2>

<p>
	فيما يلي مزيد من الأمثلة عن كيفية حدوث الأخطاء في C++‎. يمكن أن تؤدي الإشارة إلى أعضاء غير ساكنين (non-static members) في قوائم المهيئات (initializer lists) قبل بدء تنفيذ المُنشئ إلى حدوث سلوك غير معرَّف، ذلك أنه في هذه المرحلة لن يكون جميع الأعضاء قد أُنشِؤوا بعد. انظر هذا المُقتطف من المسوَّدة القياسية:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		12.7.1: بالنسبة لكائن ذي مُنشئ غير اعتيادي (non-trivial constructor)، ستؤدّي الإشارة إلى عضو غير ساكن أو صنف أساسي للكائن قبل أن يبدأ تنفيذ المُنشئ إلى نتائج غير مُحدّدة.
	</p>
</blockquote>

<p>
	هذا مثال على ذلك:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_98" style="">
<span class="kwd">struct</span><span class="pln"> W </span><span class="pun">{</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> j</span><span class="pun">;</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> X </span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">virtual</span><span class="pln"> W </span><span class="pun">{</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> Y </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p</span><span class="pun">;</span><span class="pln">
    X x</span><span class="pun">;</span><span class="pln">
    Y</span><span class="pun">()</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> p</span><span class="pun">(&amp;</span><span class="pln">x</span><span class="pun">.</span><span class="pln">j</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// لم يُنشأ بعد x غير محدد، لأنّ</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	نكتفي بالحديث عن السلوك غير المُعرَّف وننتقل بدءًا من هذا القسم وما يليه إلى الحديث عن السلوك غير المُحدَّد (Unspeciﬁed behavior).
</p>

<h2>
	قيمة لتعداد خارج النطاق
</h2>

<p>
	عند تحويل تعداد إلى نوع عددِي صحيح، وكان ذلك النوع أصغر من أن يحتفظ بقيمة التعداد، فستكون القيمة الناتجة غير محددة، انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_100" style="">
<span class="kwd">enum</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> E </span><span class="pun">{</span><span class="pln">
    X </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln">
        Y </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">,</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// char نفترض أنّ العدد 1000 لا يُمكن أن يُخزَّن في</span><span class="pln">
</span><span class="kwd">char</span><span class="pln"> c1 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">E</span><span class="pun">::</span><span class="pln">X</span><span class="pun">);</span><span class="pln"> </span><span class="com">// تساوي 1 c1 قيمة</span><span class="pln">
</span><span class="kwd">char</span><span class="pln"> c2 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">E</span><span class="pun">::</span><span class="pln">Y</span><span class="pun">);</span><span class="pln"> </span><span class="com">// غير معينة c2 قيمة</span></pre>

<p>
	كذلك عند تحويل عدد صحيح إلى تعداد، وكانت قيمة العدد الصحيح خارج نطاق قيم التعداد، فإنّ القيمة الناتجة ستكون غير محددة. انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_102" style="">
<span class="kwd">enum</span><span class="pln"> </span><span class="typ">Color</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    RED </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln">
        GREEN </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln">
        BLUE </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">Color</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Color</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="lit">4</span><span class="pun">);</span></pre>

<p>
	بالمقابل، لمّا كانت قيمة المصدر في المثال التالي تقع في نطاق التعداد، فإنّ السلوك <strong>لن يكون</strong> "غير معيّن"، رغم أنّها لا تساوي أيّ عدّاد (enumerator):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_104" style="">
<span class="kwd">enum</span><span class="pln"> </span><span class="typ">Scale</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    ONE </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln">
        TWO </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln">
        FOUR </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">Scale</span><span class="pln"> s </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Scale</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="lit">3</span><span class="pun">);</span></pre>

<p>
	هنا، ستكون قيمة <code>‎s‎</code> مساوية لـ 3، ولن تساوي <code>‎ONE‎</code> أو <code>‎TWO‎</code> أو <code>‎FOUR‎</code>.
</p>

<h2>
	ترتيب تقييم وسائط دالة (Evaluation order of function arguments)
</h2>

<p>
	إذا كان لدالّة ما عدّة وسائط، فسيكون ترتيب تقييمها غير محدد. انظر المثال التالي، حيث يحتمل أن تطبع الشيفرة التالية إمّا <code>‎x = 1, y = 2‎</code> أو <code>‎x = 2, y = 1‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_106" style="">
<span class="typ">int</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> y</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    printf</span><span class="pun">(</span><span class="str">"x = %d, y = %d\n"</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> get_val</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">++</span><span class="pln">x</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    f</span><span class="pun">(</span><span class="pln">get_val</span><span class="pun">(),</span><span class="pln"> get_val</span><span class="pun">());</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 17</strong>
</p>

<p>
	في C++‎ 17، يظل ترتيب تقييم وسائط الدالّة غير محدد، رغم أن كل وسائط الدالة تُقيّم بشكل كامل كما يُضمن تقييم كائن الاستدعاء calling object قبل تقييم وسائط الدالة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_108" style="">
<span class="kwd">struct</span><span class="pln"> from_int </span><span class="pun">{</span><span class="pln">
    from_int</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"from_int ("</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> x </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">")\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> make_int</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"make_int ("</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> x </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">")\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">(</span><span class="pln">from_int a</span><span class="pun">,</span><span class="pln"> from_int b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> bar</span><span class="pun">(</span><span class="pln">from_int a</span><span class="pun">,</span><span class="pln"> from_int b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> which_func</span><span class="pun">(</span><span class="kwd">bool</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> b</span><span class="pun">?</span><span class="str">"foo"</span><span class="pun">:</span><span class="str">"bar"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> b </span><span class="pun">?</span><span class="pln"> foo </span><span class="pun">:</span><span class="pln"> bar</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> argc</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">*</span><span class="kwd">const</span><span class="pun">*</span><span class="pln"> argv</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    which_func</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)(</span><span class="pln">make_int</span><span class="pun">(</span><span class="lit">1</span><span class="pun">),</span><span class="pln"> make_int</span><span class="pun">(</span><span class="lit">2</span><span class="pun">));</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	سيكون الخرج إمّا:
</p>

<pre class="ipsCode">
bar
make_int(1)
from_int(1)
make_int(2)
from_int(2)
</pre>

<p>
	أو:
</p>

<pre class="ipsCode">
bar
make_int(2)
from_int(2)
make_int(1)
from_int(1)
</pre>

<p>
	قد لا تطبع الشيفرة السلسلة النصية <code>‎bar‎</code> بعد <code>‎make‎</code> أو <code>‎from‎</code>، وقد لا تطبع ما يلي أيضًا:
</p>

<pre class="ipsCode">
bar
make_int(2)
make_int(1)
from_int(2)
from_int(1)
</pre>

<p>
	كانت طباعة <code>‎bar‎</code> بعد <code>‎make_int‎</code> قبل C++‎ 17 غير جائزة، ولا تنفيذ <code>‎make_int‎</code> s قبل <code>‎from_int‎</code>.
</p>

<h2>
	نتيجة التحويلات من النوع reinterpret_cast
</h2>

<p>
	تكون نتيجة التحويل <code>‎reinterpret_cast‎</code> من نوع مؤشر دالة إلى آخر أو من نوع مرجع دالة ما إلى آخر، تكون غير محددة. انظر المثال التالي حيث تكون قيمة <code>fp</code> غير محددة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_110" style="">
<span class="typ">int</span><span class="pln"> f</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> fp </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">reinterpret_cast</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">(*)(</span><span class="typ">int</span><span class="pun">)&gt;(&amp;</span><span class="pln">f</span><span class="pun">);</span><span class="pln"> </span></pre>

<p>
	<strong>الإصدار ≤ C++‎ 03</strong>
</p>

<p>
	بالمثل، ستكون نتيجة تحويل <code>‎reinterpret_cast‎</code> من نوع مؤشّر كائن (object pointer) إلى آخر، أو من نوع مرجع كائن (object reference) إلى آخر، غير محددة. انظر المثال التالي حيث تكون قيمة <code>p</code> غير محددة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_112" style="">
<span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> p </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">reinterpret_cast</span><span class="pun">&lt;</span><span class="kwd">char</span><span class="pun">*&gt;(&amp;</span><span class="pln">x</span><span class="pun">);</span><span class="pln"> </span></pre>

<p>
	يكافئ هذا في معظم المُصرِّفات تحويلَ <code>‎static_cast&lt;char*&gt;(static_cast&lt;void*&gt;(&amp;x))‎</code>، لذلك يشير المؤشّر الناتج <code>‎p‎</code> إلى البايت الأول من <code>‎x‎</code>، وهذا هو السلوك القياسي في C++‎ 11.
</p>

<h2>
	المساحة التي يشغلها مرجع ما
</h2>

<p>
	المرجع ليس كائنًا، إذ أنّه على عكس الكائنات، لا يحتل بالضرورة مجموعة متجاورة من البايتات في الذاكرة، ولا يحدّد المعيار مسألة ما إذا كان المرجع يتطلب أيّ تخزين أصلًا.
</p>

<p>
	وبعض المزايا في C++‎ 17 تجعل مسألة التحقق من أيّ تخزين قد يشغله المرجع بشكل محمول (portably) أمرًا مستحيلًا:
</p>

<ul>
<li>
		فعند تطبيق <code>‎sizeof‎</code> على مرجع ما فإنها تُعيد حجم النوع المشار إليه، ومن ثم لن تعطي معلومات عمّا إذا كان المرجع يشغل مساحة تخزين ما.
	</li>
	<li>
		مصفوفات المراجع (Arrays of references) غير جائزة، لذا لا يمكن التحقّق من عنواني عنصرين متتاليين لمرجع يشير إلى مصفوفات بُغية تحديد حجم المرجع.
	</li>
	<li>
		في حال أخذ عنوان مرجع ما، فإنّ النتيجة ستكون عنوان العنصر المشار إليه في ذلك المرجع، لذا لا يمكننا الحصول على مؤشّر يشير إلى المرجع نفسه.
	</li>
	<li>
		إذا كان لصنف ما عضو مرجعي (reference member)، فإنّ محاولة استخراج عنوان ذلك العضو باستخدام <code>‎offsetof‎</code> ستؤدي إلى سلوك غير معرَّف، لأنّ مثل هذا الصنف لن يكون صنفَ تخطيط قياسي (standard-layout class).
	</li>
	<li>
		إذا كان لصنف ما عضوٌ مرجعي، فلن يعدّ الصنف تخطيطًا قياسيًا (standard layout)، لذا سينتج عن محاولة الوصول إلى البيانات المُستخدمة لتخزين المرجع سلوكًا غير معرَّف، أو سلوكًا غير محدد.
	</li>
</ul>
<p>
	وعمليًا، يمكن في بعض الحالات تنفيذ متغيّر مرجعي (reference variable) على هيئة متغيّر مؤشّر (pointer variable)، وسيشغل حينها نفس مساحة التخزين التي يشغلها المؤشّر، بينما قد لا يشغل المرجع في حالات أخرى أيّ مساحة على الإطلاق نتيجة لعمليات التحسين (optimisation). على سبيل المثال، في الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_114" style="">
<span class="kwd">void</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pun">&amp;</span><span class="pln"> r </span><span class="pun">=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// r افعل شيئا ما بـ</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يستطيع المُصرِّف معاملة <code>‎r‎</code> كاسم بديل (alias) لـ <code>‎x‎</code>، واستبدال كل تكرارات <code>‎x‎</code> في بقية الدالّة <code>‎f‎</code> بـ <code>r</code>، مع عدم تخصيص أيّ ذاكرة لـ <code>‎r‎</code>.
</p>

<h2>
	حالة "منقول-منه" Moved-from لأغلب أصناف المكتبات القياسية
</h2>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	تُترك جميع حاويات المكتبات القياسية في حالة <strong>غير محددة لكن صالحة</strong> بعد النقل منها. على سبيل المثال، في الشيفرة التالية، <code>‎v2‎</code> ستتضمّن <code>‎{1, 2, 3, 4}‎</code> بعد النقل، لكن لن تكون <code>‎v1‎</code> فارغة بالضرورة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_116" style="">
<span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> v1</span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">};</span><span class="pln"> 
    std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v2 </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">v1</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تكون لبعض الأصناف حالة مُحدّدة بدقة بعد النقل منها، والحالة الأهم هي حالة <code>std::unique_ptr&lt;T&gt;‎</code>، التي تكون فارغة بعد النقل منها.
</p>

<h2>
	نتيجة المقارنة بين المؤشّرات
</h2>

<p>
	ستكون النتيجة غير محددة عند مقارنة مؤشّرين باستخدام العوامل <code>‎&lt;‎</code> أو <code>‎&gt;‎</code> أو <code>‎&lt;=‎</code> أو <code>‎&gt;=‎</code>، وذلك في الحالات التالية:
</p>

<ul>
<li>
		إذا كانت المؤشّرات تشير إلى مصفوفات مختلفة، إذ تُعدّ الكائنات التي ليست مصفوفات عبارة عن مصفوفات من الحجم 1.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_118" style="">
<span class="typ">int</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> y</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> b1 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">x </span><span class="pun">&lt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">y</span><span class="pun">;</span><span class="pln"> </span><span class="com">// غير محدد</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">[</span><span class="lit">10</span><span class="pun">];</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> b2 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">a</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">a</span><span class="pun">[</span><span class="lit">1</span><span class="pun">];</span><span class="pln"> </span><span class="com">// true</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> b3 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">a</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">x</span><span class="pun">;</span><span class="pln"> </span><span class="com">// غير محدد</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> b4 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">a </span><span class="pun">+</span><span class="pln"> </span><span class="lit">9</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">a </span><span class="pun">+</span><span class="pln"> </span><span class="lit">10</span><span class="pun">);</span><span class="pln"> </span><span class="com">// true</span><span class="pln">
</span><span class="com">// إلى الموضع الذي يلي المصفوفة a+10 تشير</span></pre>

<ul>
<li>
		إذا كانت المؤشرات تشير إلى داخل نفس الكائن، لكن إلى أعضاء ذات متحكمات وصول (access control) مختلفة.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_120" style="">
<span class="kwd">class</span><span class="pln"> A </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> y</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">bool</span><span class="pln"> f1</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">x </span><span class="pun">&lt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">y</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="com">// true</span><span class="pln">
    </span><span class="kwd">bool</span><span class="pln"> f2</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">x </span><span class="pun">&lt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">z</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="com">// غير محدد</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> z</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	‎
</p>

<h2>
	التحويل الساكن من من قيمة من النوع void*‎
</h2>

<p>
	إذا حُوِّلَت قيمةٌ من نوع <code>‎void*‎</code> إلى مؤشّر يشير إلى نوع <code>‎T*‎</code>، لكن لم تحاذى بشكل صحيح مع <code>‎T‎</code>، فستكون قيمة المؤشّر الناتجة غير محددة. انظر المثال التالي، لنفترض أن <code>(alignof(int</code> تساوي 4:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_122" style="">
<span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">void</span><span class="pun">*</span><span class="pln"> p1 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">x</span><span class="pun">;</span><span class="pln">
</span><span class="com">// إنجاز بعض العمليات الحسابية على المؤشر</span><span class="pln">
</span><span class="kwd">void</span><span class="pun">*</span><span class="pln"> p2 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="kwd">char</span><span class="pun">*&gt;(</span><span class="pln">p1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pun">*</span><span class="pln"> p3 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">*&gt;(</span><span class="pln">p2</span><span class="pun">);</span></pre>

<p>
	قيمة <code>‎p3‎</code> غير محددة لأنّ <code>‎p2‎</code> لا يمكن أن تشير إلى كائن من النوع <code>‎int‎</code>؛ فمُحاذاة عنوان قيمتها غير صحيحة.
</p>

<h2>
	ترتيب تهيئة الكائنات العامّة عبر وحدة الترجمة
</h2>

<p>
	يكون ترتيب تهيئة المتغيّرات العامة محددًا داخل وحدة الترجمة، بينما يكون ترتيب التهيئة عبر عدة وحدات ترجمة غير محدد. لذلك فالبرنامج الذي به الملفات التالية:
</p>

<ul>
<li>
		foo.cpp
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_124" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> dummyFoo </span><span class="pun">=</span><span class="pln"> </span><span class="pun">((</span><span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"foo"</span><span class="pun">),</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span></pre>

<ul>
<li>
		bar.cpp
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_126" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> dummyBar </span><span class="pun">=</span><span class="pln"> </span><span class="pun">((</span><span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"bar"</span><span class="pun">),</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span></pre>

<ul>
<li>
		main.cpp
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_128" style="">
<span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span></pre>

<p>
	قد يُنتِج الخرج التالي:
</p>

<pre class="ipsCode">
foobar
</pre>

<p>
	أو:
</p>

<pre class="ipsCode">
barfoo
</pre>

<p>
	وقد يؤدّي ذلك إلى <strong>إخفاق ترتيب التهيئة الساكنة</strong> (Static Initialization Order Fiasco).
</p>

<h2>
	الاتحادات Unions والسلوك غير المعرَّف
</h2>

<p>
	انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_130" style="">
<span class="kwd">union</span><span class="pln"> U </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">short</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">float</span><span class="pln"> c</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
U u</span><span class="pun">;</span><span class="pln">
u</span><span class="pun">.</span><span class="pln">a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">u</span><span class="pun">.</span><span class="pln">b </span><span class="pun">==</span><span class="pln"> </span><span class="lit">10</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	سينجم عن الشيفرة أعلاه سلوك غير معرَّف، ذلك أن <code>a</code> كان آخر عضو يُكتَب فيه. وتجيز الكثير من المصرّفات هذا الأمر، وقد تكتفي بإصدار تحذير، بيْد أنّ النتيجة ستكون "كما هو متوقع"؛ أن هذه إضافة للمصرّف (extension compiler)، لذا لا يمكن ضمان هذا السلوك في جميع المصرّفات (فهي شيفرة غير محمولة ولا متوافقة).
</p>

<p>
	الاتحادات (Unions) هي بنيات مخصصة تحتلّ أعضاؤها مساحة مشتركة في الذاكرة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_132" style="">
<span class="kwd">union</span><span class="pln"> U </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">short</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">float</span><span class="pln"> c</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
U u</span><span class="pun">;</span><span class="pln">
</span><span class="com">//سيكونان متساويين a و b عنوانا</span><span class="pln">
</span><span class="pun">(</span><span class="kwd">void</span><span class="pun">*)&amp;</span><span class="pln">u</span><span class="pun">.</span><span class="pln">a </span><span class="pun">==</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">void</span><span class="pun">*)&amp;</span><span class="pln">u</span><span class="pun">.</span><span class="pln">b</span><span class="pun">;</span><span class="pln">
</span><span class="pun">(</span><span class="kwd">void</span><span class="pun">*)&amp;</span><span class="pln">u</span><span class="pun">.</span><span class="pln">a </span><span class="pun">==</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">void</span><span class="pun">*)&amp;</span><span class="pln">u</span><span class="pun">.</span><span class="pln">c</span><span class="pun">;</span><span class="pln">
</span><span class="com">// إسناد قيمة إلى أيّ عضو من الاتحاد يغير الذاكرة المشتركة</span><span class="pln">
u</span><span class="pun">.</span><span class="pln">c </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4.</span><span class="pln"> f</span><span class="pun">;</span><span class="pln">
u</span><span class="pun">.</span><span class="pln">a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">
u</span><span class="pun">.</span><span class="pln">c </span><span class="pun">!=</span><span class="pln"> </span><span class="lit">4.</span><span class="pln"> f</span><span class="pun">;</span></pre>

<p>
	تساعد الاتحادات على ترشيد استخدام الذاكرة المخصّصة للبيانات الحصرية (exclusive data)، كما في تنفيذ أنواع مختلطة من البيانات.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4304_134" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">AnyType</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">enum</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        IS_INT</span><span class="pun">,</span><span class="pln">
        IS_FLOAT
    </span><span class="pun">}</span><span class="pln">
    type</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">union</span><span class="pln"> </span><span class="typ">Data</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> as_int</span><span class="pun">;</span><span class="pln">
        </span><span class="typ">float</span><span class="pln"> as_float</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    value</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">AnyType</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">):</span><span class="pln"> type</span><span class="pun">(</span><span class="pln">IS_INT</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        value</span><span class="pun">.</span><span class="pln">as_int </span><span class="pun">=</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="typ">AnyType</span><span class="pun">(</span><span class="typ">float</span><span class="pln"> f</span><span class="pun">):</span><span class="pln"> type</span><span class="pun">(</span><span class="pln">IS_FLOAT</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        value</span><span class="pun">.</span><span class="pln">as_float </span><span class="pun">=</span><span class="pln"> f</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> get_int</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> IS_INT</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> value</span><span class="pun">.</span><span class="pln">as_int</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">else</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pun">)</span><span class="pln"> value</span><span class="pun">.</span><span class="pln">as_float</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="typ">float</span><span class="pln"> get_float</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> IS_FLOAT</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> value</span><span class="pun">.</span><span class="pln">as_float</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">else</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="typ">float</span><span class="pun">)</span><span class="pln"> value</span><span class="pun">.</span><span class="pln">as_int</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617022794="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصول:
</p>

<ul>
<li>
		Chapter 104: Undefined Behavior
	</li>
	<li>
		Chapter 140: More undefined behaviors in C++‎
	</li>
	<li>
		Chapter 121: Unspecified behavior
	</li>
	<li>
		Chapter 111: Unions
	</li>
</ul>
<p>
	من كتاب <a data-ss1617022794="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">1022</guid><pubDate>Tue, 13 Oct 2020 13:02:00 +0000</pubDate></item><item><title>&#x642;&#x627;&#x639;&#x62F;&#x629; SFINAE (&#x641;&#x634;&#x644; &#x627;&#x644;&#x62A;&#x639;&#x648;&#x64A;&#x636; &#x644;&#x64A;&#x633; &#x62E;&#x637;&#x623;) &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-sfinae-%D9%81%D8%B4%D9%84-%D8%A7%D9%84%D8%AA%D8%B9%D9%88%D9%8A%D8%B6-%D9%84%D9%8A%D8%B3-%D8%AE%D8%B7%D8%A3-%D9%81%D9%8A-cpp-r1021/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_03/46.png.f81526f89cab59d34e1a884c2f28ece7.png" /></p>

<p>
	كلمة SFINAE هي اختصار للجملة: Substitution Failure Is Not An Error، وتشير إلى أنّه لا تُعد الشيفرات سيئة الصيغة بسبب تعويض الأنواع (أو القيم) لأجل استنساخ قالب دالة (instantiate a function template) أو قالب صنف، لا تُعدُّ خطأً تصريفيا فادحًا (hard compile error)، وإنّما يتم التعامل معها على أنّها فشل في استنتاج النوع فقط.
</p>

<p>
	فشل استنتاج النوع في قوالب دوالّ الاستنساخ (instantiating function templates) أو تخصيصات قالب الصنف (class template specializations) يؤدي إلى إهمال ذلك النوع أثناء محاولة استنتاج النوع (كما لو أنّ ذلك النوع المرشح المُستبعد لم يكن موجودًا من البداية).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1717_7" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> begin</span><span class="pun">(</span><span class="pln">T</span><span class="pun">&amp;</span><span class="pln"> c</span><span class="pun">)</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">c</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> c</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">();</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="typ">size_t</span><span class="pln"> N</span><span class="pun">&gt;</span><span class="pln">
    T</span><span class="pun">*</span><span class="pln"> begin</span><span class="pun">(</span><span class="pln">T </span><span class="pun">(&amp;</span><span class="pln">arr</span><span class="pun">)[</span><span class="pln">N</span><span class="pun">])</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> arr</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> vals</span><span class="pun">[</span><span class="lit">10</span><span class="pun">];</span><span class="pln">
begin</span><span class="pun">(</span><span class="pln">vals</span><span class="pun">);</span></pre>

<p>
	تفشل المحاولة الأولى لتعويض قالب الدالة في <code>(begin(vals</code> من الشيفرة السابقة، لأن صيغة <code>()vals.begin</code> خطأ، لكن لا يعطي هذا خطأً بل ستُزال تلك الدالة من ترشيحها للتحميل الزائد، تاركة إيانا مع التحميل الزائد للمصفوفات (array overload).
</p>

<p>
	لا يعدُّ فشل الاستبدال فشلًا في الاستنتاج إلّا في السياق الفوري (immediate context)، أمّا في الحالات الأخرى، فستُعد أخطاء فادحة (hard errors).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1717_9" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> add_one</span><span class="pun">(</span><span class="pln">T</span><span class="pun">&amp;</span><span class="pln"> val</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> val </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4</span><span class="pun">;</span><span class="pln">
add_one</span><span class="pun">(</span><span class="pln">i</span><span class="pun">);</span><span class="pln">    </span><span class="com">// حسنا</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string msg </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Hello"</span><span class="pun">;</span><span class="pln">
add_one</span><span class="pun">(</span><span class="pln">msg</span><span class="pun">);</span><span class="pln">    </span><span class="com">// error. msg += 1 is ill-formed for std::string, but this</span><span class="pln">
</span><span class="com">// T لم يحدث الفشل في السياق الفوري لتعويض</span></pre>

<h2>
	void_t
</h2>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	<code>‎void_t‎</code> هي دالّة وصفية (meta-function) تحول الأنواع إلى النوع الفارغ (type void)، وغرضها الأساسي هو تسهيل كتابة سمات النوع (type traits). ستكون <code>std::void_t</code> جزء من C++‎ 17، ولكنّ تنفيذها سهل على أي حال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1717_11" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">using</span><span class="pln"> </span><span class="typ">void_t</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">;</span></pre>

<p>
	تتطّلب بعض المٌصرّفات تنفيذًا مختلفًا قليلاً:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1717_13" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> make_void
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> type </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pun">...</span><span class="pln">T </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> </span><span class="typ">void_t</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> make_void </span><span class="pun">&lt;</span><span class="pln"> T</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;::</span><span class="pln">type</span><span class="pun">;</span></pre>

<p>
	التطبيق الأساسي لـ <code>‎void_t‎</code> هو كتابة سمات النوع التي تتحقّق من صحّة عبارة برمجية. على سبيل المثال، دعنا نتحقّق ممّا إذا كان نوع ما له دالة تابعة <code>‎foo()‎</code> لا تأخذ أيّة وسائط:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1717_15" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> has_foo</span><span class="pun">:</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">false_type </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> has_foo</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> </span><span class="typ">void_t</span><span class="pun">&lt;</span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">declval</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&amp;&gt;().</span><span class="pln">foo</span><span class="pun">())&gt;&gt;</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">true_type </span><span class="pun">{};</span></pre>

<p>
	سيحاول المُصرّف عند محاولة استنساخ <code>‎has_foo&lt;T&gt;::value‎</code> أن يبحث عن أفضل تخصيص لـ <code>‎has_foo&lt;T, void&gt;‎</code>. لدينا خياران هنا، الأوليّ والثانوي، يتطلب الثانوي استنساخ التعبير الأساسي (underlying expression):
</p>

<ul>
<li>
		إذا لم يحتوي<code>‎T‎</code> على دالة تابعة <code>‎foo()‎</code>، فسيُحوّل النوع المُعاد إلى <code>‎void‎</code>، وسيُفضَّل التخصِيص (specialization) على القالب الأوّلي بناءً على قواعد الترتيب الجزئي للقوالب (template partial ordering rules). لذا، فإنّ <code>has_foo&lt;T&gt;::value</code> ستساوي <code>true</code>
	</li>
	<li>
		إذا لم يكن <code>‎T‎</code> يتحوي على تلك الدالة التابعة (أو إذا كانت موجودة، بيْد أنّها تتطّلب أكثر من وسيط واحد)، فستفشل عملية الاستبدال بالتخصيص، وسنعود إلى القالب الأساسي. وعندئذ ستساوي <code>‎has_foo&lt;T&gt;::value‎</code> القيمة <code>‎false‎</code>.
	</li>
</ul>
<p>
	هذا المثال لا يستخدم <code>‎std::declval‎</code> أو <code>‎decltype‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1717_17" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> can_reference</span><span class="pun">:</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">false_type </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> can_reference</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">void_t</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&amp;&gt;&gt;</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">true_type </span><span class="pun">{};</span></pre>

<p>
	لاحظ النمط الشائع لاستخدام الوسيط الفارغ (void argument). يمكننا كتابة الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1717_19" style="">
<span class="kwd">struct</span><span class="pln"> details
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> Z</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="typ">Ts</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">struct</span><span class="pln"> can_apply</span><span class="pun">:</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">false_type </span><span class="pun">{};</span><span class="pln">
    </span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> Z</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="typ">Ts</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">struct</span><span class="pln"> can_apply</span><span class="pun">&lt;</span><span class="pln">Z</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">void_t</span><span class="pun">&lt;</span><span class="pln">Z </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Ts</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;&gt;,</span><span class="pln"> </span><span class="typ">Ts</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;:</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">true_type </span><span class="pun">{};</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> Z</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="typ">Ts</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> can_apply </span><span class="pun">=</span><span class="pln"> details</span><span class="pun">::</span><span class="pln">can_apply</span><span class="pun">&lt;</span><span class="pln">Z</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Ts</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">;</span></pre>

<p>
	والتي تتجّنب استخدام <code>‎std::void_t‎</code>، وتستخدم <code>‎can_apply‎</code> بدلًا من ذلك، والتي تتصرّف كمحدّد (indicator) يوضح ما إذا كان النوع المتوفّر كوسيط أوّل للقالب مُصاغًا صيغة صحيحة بعد استبدال الأنواع الأخرى فيه. يمكن الآن إعادة كتابة الأمثلة السابقة باستخدام <code>‎can_apply‎</code> على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1717_21" style="">
<span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">ref_t</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> T</span><span class="pun">&amp;;</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> can_reference </span><span class="pun">=</span><span class="pln"> can_apply</span><span class="pun">&lt;</span><span class="typ">ref_t</span><span class="pun">,</span><span class="pln"> T</span><span class="pun">&gt;;</span><span class="pln">   </span><span class="com">// مصاغة صيغة صحيحة T&amp; </span></pre>

<p>
	و:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1717_23" style="">
<span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> dot_foo_r </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">declval</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&amp;&gt;().</span><span class="pln">foo</span><span class="pun">());</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> can_dot_foo </span><span class="pun">=</span><span class="pln"> can_apply</span><span class="pun">&lt;</span><span class="pln"> dot_foo_r</span><span class="pun">,</span><span class="pln"> T </span><span class="pun">&gt;;</span><span class="pln">   </span><span class="com">// مصاغة صيغة صَحيحة T.foo() </span></pre>

<p>
	والتي تبدو أبسط من النسخ السابقة، هناك مقترحات بعد الإصدار C++‎ 17 لإنشاء سمات <code>‎std‎</code> مماثلة لـ <code>‎can_apply‎</code>.
</p>

<p>
	يُعزى اكتشاف فائدة <code>‎void_t‎</code> إلى والتر براون (Walter Brown)، في <a data-ss1617022796="1" href="https://www.youtube.com/watch?v=a0FliKwcwXE&amp;feature=youtu.be&amp;t=1747" rel="external nofollow">العرض الرائع</a> الذي قدّمه في CppCon 2016.
</p>

<h2>
	enable_if
</h2>

<p>
	<code>std::enable_if</code> هي أداة مساعدة لاستخدام الشروط المنطقية لتفعيل قاعدة SFINAE. وتُعرّف على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1717_25" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> </span><span class="typ">Cond</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">Result</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> enable_if </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">Result</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> enable_if</span><span class="pun">&lt;</span><span class="kwd">true</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Result</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> type </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Result</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span></pre>

<p>
	بمعنى أنّ <code>‎enable_if&lt;true, R&gt;::type‎</code> هو اسم بديل (alias) لـ <code>‎R‎</code>، في حين أنّ صيغة <code>‎enable_if&lt;false, T&gt;::type‎</code> غير صحيحة نظرًا لأنّ تخصيص <code>‎enable_if‎</code> لا يحتوي على نوع عضوي (member type‏) <code>‎type‎</code>.
</p>

<p>
	نستطيع استخدام <code>std::enable_if</code> لتقييد القوالب:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1717_27" style="">
<span class="typ">int</span><span class="pln"> negate</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">-</span><span class="pln">i</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> F</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> negate</span><span class="pun">(</span><span class="pln">F f</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">-</span><span class="pln">f</span><span class="pun">();</span><span class="pln"> </span><span class="pun">}</span></pre>

<p>
	هنا سيفشل استدعاء <code>‎negate(1)‎</code> بسبب الغموض، لكنّ <a data-ss1617022796="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-22-%D8%A7%D9%84%D8%AA%D8%AD%D9%85%D9%8A%D9%84-%D8%A7%D9%84%D8%B2%D8%A7%D8%A6%D8%AF-overloading-%D8%AA%D8%AD%D9%84%D9%8A%D9%84%D9%87-%D9%88%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D9%87-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D9%81%D9%8A-cpp-r934/" rel="">التحميل الزائد</a> الثاني ليس مُعدًّا لاستخدامه مع الأنواع العددية الصحيحة، لذلك يمكننا إضافة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1717_29" style="">
<span class="typ">int</span><span class="pln"> negate</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">-</span><span class="pln">i</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> F</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">enable_if</span><span class="pun">&lt;!</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_arithmetic</span><span class="pun">&lt;</span><span class="pln">F</span><span class="pun">&gt;::</span><span class="pln">value</span><span class="pun">&gt;::</span><span class="pln">type</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> negate</span><span class="pun">(</span><span class="pln">F f</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">-</span><span class="pln">f</span><span class="pun">();</span><span class="pln"> </span><span class="pun">}</span></pre>

<p>
	الآن، سيؤدّي استنساخ <code>‎negate&lt;int&gt;‎</code> إلى فشل التعويض لأنّ <code>‎!std::is_arithmetic&lt;int&gt;::value‎</code> تساوي <code>‎false‎</code>. لكن بسبب قاعدة SFINAE، فلَن يكون هذا خطأ فادحًا (hard error)، وإنّما سيُزال هذا المرشّح من مجموعة المرشحين للتحميل الزائد وحسب. ونتيجة لذلك، لن يكون لـ <code>negate(1)‎</code> إلّا مرشح واحد وهو الذي سيُستدعى.
</p>

<h3>
	متى نستخدَمها
</h3>

<p>
	تذكر أنّ <code>‎std::enable_if‎</code> هو مُساعد يعمل مع قاعدة SFINAE، لكن ليس هو الذي يجعلها تعمل في المقام الأول، دعنا ننظر في البديلين التاليين لتنفيذ وظائف مماثلة لـ <code>‎std::size‎</code>، وهي مجموعة تحميل زائد لـ <code>‎size(arg)‎</code> تعيد حجم الحاوية أو المصفوفة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1717_31" style="">
<span class="com">// للحاويات</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">Cont</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> size1</span><span class="pun">(</span><span class="typ">Cont</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> cont</span><span class="pun">)</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln"> cont</span><span class="pun">.</span><span class="pln">size</span><span class="pun">()</span><span class="pln"> </span><span class="pun">);</span><span class="pln">

</span><span class="com">// للمصفوفات</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">Elt</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> </span><span class="typ">Size</span><span class="pun">&gt;</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> size1</span><span class="pun">(</span><span class="typ">Elt</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">(&amp;</span><span class="pln">arr</span><span class="pun">)[</span><span class="typ">Size</span><span class="pun">]);</span><span class="pln">

</span><span class="com">// حذف التنفيذ</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">Cont</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> is_sizeable</span><span class="pun">;</span><span class="pln">

</span><span class="com">// للحاويات</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">Cont</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">enable_if_t</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_sizeable</span><span class="pun">&lt;</span><span class="typ">Cont</span><span class="pun">&gt;::</span><span class="pln">value</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> size2</span><span class="pun">(</span><span class="typ">Cont</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> cont</span><span class="pun">);</span><span class="pln">

</span><span class="com">// للمصفوفات</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">Elt</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> </span><span class="typ">Size</span><span class="pun">&gt;</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> size2</span><span class="pun">(</span><span class="typ">Elt</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">(&amp;</span><span class="pln">arr</span><span class="pun">)[</span><span class="typ">Size</span><span class="pun">]);</span></pre>

<p>
	على افتراض أنّ <code>‎is_sizeable‎</code> مكتوبة بشكل صحيح، فيجب أن يكون هذان التصريحان متكافئين تمامًا بحسب قاعدةSFINAE، فأيّهما أسهل في الكتابة وفي المراجعة والفهم؟
</p>

<p>
	سنحاول الآن تنفيذ بعض المساعِدات الحسابية التي تتفادى طفح (overflow) الأعداد الصحيحة غير المؤشّرة لصالح سلوك الالتفاف (wraparound) أو السلوك القابل للتعديل (modular). هذا يعني مثلًا أنّ <code>‎incr(i, 3)‎</code> ستكافئ <code>‎i += 3‎</code> باستثناء حقيقة أنّ النتيجة ستكون دائمًا مُعرّفة حتى لو كان <code>‎i‎</code> عددًا صحيحًا يساوي <code>‎INT_MAX‎</code>. ما يلي بديلان ممكنان:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1717_33" style="">
<span class="com">// معالجة الأنواع المؤشَّرة</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">Int</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> incr1</span><span class="pun">(</span><span class="typ">Int</span><span class="pun">&amp;</span><span class="pln"> target</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Int</span><span class="pln"> amount</span><span class="pun">)</span><span class="pln">
</span><span class="pun">-&gt;</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">void_t</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">[</span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="typ">Int</span><span class="pun">&gt;(-</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="typ">Int</span><span class="pun">&gt;(</span><span class="lit">0</span><span class="pun">)]&gt;;</span><span class="pln">

</span><span class="com">// target += amount معالجة الأنواع غير المؤشَّرة عبر</span><span class="pln">
</span><span class="com">// بما أنّ حسابيات العناصر غير المؤشَّرة تتصرف كما هو مطلوب</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">Int</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> incr1</span><span class="pun">(</span><span class="typ">Int</span><span class="pun">&amp;</span><span class="pln"> target</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Int</span><span class="pln"> amount</span><span class="pun">)</span><span class="pln">
</span><span class="pun">-&gt;</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">void_t</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">[</span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="typ">Int</span><span class="pun">&gt;(</span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="typ">Int</span><span class="pun">&gt;(-</span><span class="lit">1</span><span class="pun">)]&gt;;</span><span class="pln">

</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">Int</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">enable_if_t</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_signed</span><span class="pun">&lt;</span><span class="typ">Int</span><span class="pun">&gt;::</span><span class="pln">value</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> incr2</span><span class="pun">(</span><span class="typ">Int</span><span class="pun">&amp;</span><span class="pln"> target</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Int</span><span class="pln"> amount</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">Int</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">enable_if_t</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_unsigned</span><span class="pun">&lt;</span><span class="typ">Int</span><span class="pun">&gt;::</span><span class="pln">value</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> incr2</span><span class="pun">(</span><span class="typ">Int</span><span class="pun">&amp;</span><span class="pln"> target</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Int</span><span class="pln"> amount</span><span class="pun">);</span></pre>

<p>
	مرّة أخرى، أيّهما أسهل في الكتابة، وأيّهما أسهل في المراجعة والفهم؟
</p>

<p>
	تتمثّل قوة <code>‎std::enable_if‎</code> في طريقة تعاملها مع إعادة الإنتاج (refactoring) وتصميم الواجهات البرمجية، فإذا كان الغرض من <code>‎is_sizeable&lt;Cont&gt;::value‎</code> هو التحقّق من صحّة <code>‎cont.size()‎</code>، فقد يكون استخدام التعبير كما يظهر في <code>‎size1‎</code> أوجز، رغم أنّ ذلك قد يعتمد على ما إذا كانت <code>‎is_sizeable‎</code> ستُستخدَم في العديد من المواضع أم لا. على النقيض من ذلك، فإنّ <code>‎std::is_signed‎</code> أكثر وضوحًا ممّا كانت عليه عندما كان تنفيذها يتسرّب إلى تصريح <code>‎incr1‎</code>.
</p>

<h2>
	is_detected
</h2>

<p>
	لتعميم إنشاء type_trait استنادًا إلى قاعدة SFINAE، فهناك بعض السمات التجريبية، وهي: <code>‎detected_or‎</code> و <code>‎detected_t‎</code> و <code>‎is_detected‎</code>.
</p>

<p>
	ومع معاملات القوالب <code>‎typename Default‎</code> و <code>‎template &lt;typename...&gt; Op‎</code> و <code>‎typename ... Args‎</code>:
</p>

<ul>
<li>
		<code>‎is_detected‎</code>: هو اسم بديل لـ <code>std::true_type</code> أو <code>std::false_type</code> اعتمادًا على صلاحية <code>Op&lt;Args...&gt;</code>
	</li>
	<li>
		<code>‎detected_t‎</code>: هو اسم بديل لـ <code>Op&lt;Args...&gt;‎</code> أو <code>‎nonesuch‎</code> اعتمادًا على صلاحية <code>Op&lt;Args...&gt;‎</code>.
	</li>
	<li>
		<code>‎detected_or‎</code>: هو اسم بديل لبنية لها <code>‎value_t‎</code> مرصودة (<code>‎is_detected‎</code>)، ونوع <code>‎type‎</code> يحقّق<code>Op&lt;Args...&gt;‎</code> أو <code>‎Default‎</code> اعتمادًا على صلاحية <code>‎Op&lt;Args...&gt;‎</code>
	</li>
</ul>
<p>
	ويمكن تنفيذ باستخدام <code>‎std::void_t‎</code> لأجل قاعدة SFINAE على النحو التالي:
</p>

<p>
	<strong>الإصدار ≥ C++‎ 17</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1717_35" style="">
<span class="kwd">namespace</span><span class="pln"> detail
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Default</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AlwaysVoid</span><span class="pun">,</span><span class="pln">
        </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Op</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="typ">Args</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">struct</span><span class="pln"> detector
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">using</span><span class="pln"> </span><span class="typ">value_t</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">false_type</span><span class="pun">;</span><span class="pln">
            </span><span class="kwd">using</span><span class="pln"> type </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Default</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">};</span><span class="pln">
    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Default</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Op</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="typ">Args</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">struct</span><span class="pln"> detector</span><span class="pun">&lt;</span><span class="typ">Default</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">void_t</span><span class="pun">&lt;</span><span class="typ">Op</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Args</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;&gt;,</span><span class="pln"> </span><span class="typ">Op</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Args</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">using</span><span class="pln"> </span><span class="typ">value_t</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">true_type</span><span class="pun">;</span><span class="pln">
            </span><span class="kwd">using</span><span class="pln"> type </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Op</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Args</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
        </span><span class="pun">};</span><span class="pln">
</span><span class="pun">}</span><span class="pln">    </span><span class="com">// تفاصيل فضاء الاسم</span><span class="pln">
</span><span class="com">// نوع خاص للإشار إلى رصد الخطأ</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> nonesuch
</span><span class="pun">{</span><span class="pln">
    nonesuch</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">delete</span><span class="pun">;</span><span class="pln">
   </span><span class="pun">~</span><span class="pln">nonesuch</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">delete</span><span class="pun">;</span><span class="pln">
   nonesuch</span><span class="pun">(</span><span class="pln">nonesuch </span><span class="kwd">const</span><span class="pun">&amp;)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">delete</span><span class="pun">;</span><span class="pln">
   </span><span class="kwd">void</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">=(</span><span class="pln">nonesuch </span><span class="kwd">const</span><span class="pun">&amp;)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">delete</span><span class="pun">;</span><span class="pln">

</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pun">...&gt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Op</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="pln"> </span><span class="typ">Args</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> is_detected </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> detail</span><span class="pun">::</span><span class="pln">detector</span><span class="pun">&lt;</span><span class="pln">nonesuch</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Op</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Args</span><span class="pun">...&gt;::</span><span class="typ">value_t</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pun">...&gt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Op</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="pln"> </span><span class="typ">Args</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">detected_t</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> detail</span><span class="pun">::</span><span class="pln">detector</span><span class="pun">&lt;</span><span class="pln">nonesuch</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Op</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Args</span><span class="pun">...&gt;::</span><span class="pln">type</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Default</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pun">...&gt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Op</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="pln"> </span><span class="typ">Args</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> detected_or </span><span class="pun">=</span><span class="pln"> detail</span><span class="pun">::</span><span class="pln">detector</span><span class="pun">&lt;</span><span class="typ">Default</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Op</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Args</span><span class="pun">...&gt;;</span></pre>

<p>
	يمكن تنفيذ السمات التي ترصد وجود تابع على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1717_37" style="">
<span class="kwd">typename</span><span class="pln"> </span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="pun">...</span><span class="typ">Ts</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> foo_type </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">declval</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;().</span><span class="pln">foo</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">declval</span><span class="pun">&lt;</span><span class="typ">Ts</span><span class="pun">&gt;()...));</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> C1 </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> C2
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> foo</span><span class="pun">(</span><span class="kwd">char</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> has_foo_char </span><span class="pun">=</span><span class="pln"> is_detected</span><span class="pun">&lt;</span><span class="pln">foo_type</span><span class="pun">,</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
</span><span class="kwd">static_assert</span><span class="pun">(!</span><span class="pln">has_foo_char</span><span class="pun">&lt;</span><span class="pln">C1</span><span class="pun">&gt;::</span><span class="pln">value</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Unexpected"</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">static_assert</span><span class="pun">(</span><span class="pln">has_foo_char</span><span class="pun">&lt;</span><span class="pln">C2</span><span class="pun">&gt;::</span><span class="pln">value</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Unexpected"</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">static_assert</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_same</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">detected_t</span><span class="pun">&lt;</span><span class="pln">foo_type</span><span class="pun">,</span><span class="pln"> C2</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">&gt;&gt;::</span><span class="pln">value</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"Unexpected"</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">static_assert</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_same</span><span class="pun">&lt;</span><span class="kwd">void</span><span class="pun">,</span><span class="pln">    </span><span class="com">// افتراضي</span><span class="pln">
    detected_or</span><span class="pun">&lt;</span><span class="kwd">void</span><span class="pun">,</span><span class="pln"> foo_type</span><span class="pun">,</span><span class="pln"> C1</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">&gt;&gt;::</span><span class="pln">value</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"Unexpected"</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">static_assert</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_same</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> detected_or</span><span class="pun">&lt;</span><span class="kwd">void</span><span class="pun">,</span><span class="pln"> foo_type</span><span class="pun">,</span><span class="pln"> C2</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">&gt;&gt;::</span><span class="pln">value</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"Unexpected"</span><span class="pun">);</span></pre>

<h2>
	تحليل تحميل زائد له عدد كبير من الخيارات
</h2>

<p>
	إذا كنت بحاجة إلى الاختيار بين عدة خيارات، فقد يكون تمكين خيار واحد فقط عبر <code>‎enable_if&lt;&gt;‎</code> مرهقًا للغاية، إذ يجب إلغاء العديد من الشروط لاستبعاد الخيارات الأخرى، وبدلاً من ذلك، يمكن اختيار ترتيب <a data-ss1617022796="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-22-%D8%A7%D9%84%D8%AA%D8%AD%D9%85%D9%8A%D9%84-%D8%A7%D9%84%D8%B2%D8%A7%D8%A6%D8%AF-overloading-%D8%AA%D8%AD%D9%84%D9%8A%D9%84%D9%87-%D9%88%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D9%87-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D9%81%D9%8A-cpp-r934/" rel="">التحميلات الزائد</a> باستخدام الوراثة، أي بإرسال الوسم (tag dispatch).
</p>

<p>
	وبدلاً من التحقق من صحّة الصيغة وكذلك التحقق من أنّ جميع الشروط الأخرى غير متحقّقة، فإنّنا سنكتفي باختبار الأشياء التي نحتاجها وحسب، ويفضل أن يكون ذلك في <code>‎decltype‎</code> في إعادة زائدة (trailing return).
</p>

<p>
	قد يؤدّي هذا إلى تجاهل الكثير من الخيارات ذات الصيغة الصحيحة، لكن نستطيع التفريق بينها باستخدام "الوسوم" (tags)، على غرار وسوم مكرّرات السمات (<code>‎random_access_tag‎</code>). وسيعمل هذا بدون مشاكل لأنّ الحصول على تطابق مباشر أفضل من الصنف الأساسي (base class)، والذي هو بدوره أفضل من الصنف الأساسي لصنف أساسي (base class of a base class)، وهكذا دواليك.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1717_39" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;algorithm&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iterator&gt;</span><span class="pln">

</span><span class="kwd">namespace</span><span class="pln"> detail
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// سيعطينا هذا عددا غير محدود من الأنواع التي ترث بعضها بعضا</span><span class="pln">
    </span><span class="kwd">template</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> N</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">struct</span><span class="pln"> pick</span><span class="pun">:</span><span class="pln"> pick </span><span class="pun">&lt;</span><span class="pln"> N </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">struct</span><span class="pln"> pick </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{};</span></pre>

<p>
	التحميل الزائد الذي نريد له أن يكون مفضَّلًا يجب أن تكون قيمة N له أكبر في <code>&lt;pick&lt;N</code>، ما يلي أول دالة قالب مساعِدة، نتابع المثال …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1717_41" style="">
<span class="pln">    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">auto</span><span class="pln"> stable_sort</span><span class="pun">(</span><span class="pln">T</span><span class="pun">&amp;</span><span class="pln"> t</span><span class="pun">,</span><span class="pln"> pick</span><span class="pun">&lt;</span><span class="lit">2</span><span class="pun">&gt;)-&gt;</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln"> t</span><span class="pun">.</span><span class="pln">stable_sort</span><span class="pun">(),</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">()</span><span class="pln"> </span><span class="pun">)</span><span class="pln">

        </span><span class="pun">{</span></pre>

<p>
	إن كانت الحاوية لديها <code>stable_sort</code> فاستخدمه، …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1717_43" style="">
<span class="pln">            t</span><span class="pun">.</span><span class="pln">stable_sort</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// المساعد سيكون ثاني أفضل تطابق ممكن</span><span class="pln">
    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">

</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> stable_sort</span><span class="pun">(</span><span class="pln">T</span><span class="pun">&amp;</span><span class="pln"> t</span><span class="pun">,</span><span class="pln"> pick</span><span class="pun">&lt;</span><span class="lit">1</span><span class="pun">&gt;)-&gt;</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln"> t</span><span class="pun">.</span><span class="pln">sort</span><span class="pun">(),</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">()</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span></pre>

<p>
	إذا كان للحاوية عضو <code>sort</code> لكن لم يكن فيها <code>stable_sort</code> فسيكون <code>sort</code> مستقرًا غالبًا، نتابع …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1717_47" style="">
<span class="pln">            t</span><span class="pun">.</span><span class="pln">sort</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// هذا المساعد سيكون آخر مرشح</span><span class="pln">
    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">auto</span><span class="pln"> stable_sort</span><span class="pun">(</span><span class="pln">T</span><span class="pun">&amp;</span><span class="pln"> t</span><span class="pun">,</span><span class="pln"> pick</span><span class="pun">&lt;</span><span class="lit">0</span><span class="pun">&gt;)-&gt;</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">stable_sort</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">begin</span><span class="pun">(</span><span class="pln">t</span><span class="pun">),</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">end</span><span class="pun">(</span><span class="pln">t</span><span class="pun">)),</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">()</span><span class="pln"> </span><span class="pun">)</span><span class="pln">

        </span><span class="pun">{</span></pre>

<p>
	الحاوية لا تحتوي على عضو <code>sort</code> أو <code>stable_sort</code> …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1717_49" style="">
<span class="pln">           std</span><span class="pun">::</span><span class="pln">stable_sort</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">begin</span><span class="pun">(</span><span class="pln">t</span><span class="pun">),</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">end</span><span class="pun">(</span><span class="pln">t</span><span class="pun">));</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// 'tags' هذه هي الدالة التي يستدعيها المستخدم، ستقوم بإرسال الاستدعاء إلى التقديم الصحيح بمساعدة</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> stable_sort</span><span class="pun">(</span><span class="pln">T</span><span class="pun">&amp;</span><span class="pln"> t</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// مع قيمة أكبر من القيم السابقة N استخدم</span><span class="pln">
        </span><span class="com">// هذا سيختار أعلى تحميل زائد من بين التحميلات الزائدة صحيحة الصيغة</span><span class="pln">
        detail</span><span class="pun">::</span><span class="pln">stable_sort</span><span class="pun">(</span><span class="pln">t</span><span class="pun">,</span><span class="pln"> detail</span><span class="pun">::</span><span class="pln">pick </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{});</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	هناك عدّة طرق أخرى للتمييز بين التحميلات الزائدة، مثل أنّ المطابقة التامة أفضل من التحويل، والتي هي بدورها أفضل من علامة الحذف (ellipsis). بالمقابل، يمكن أن يتوسّع وسم الإرسال إلى أيّ عدد من الخيارات، وهو أكثر وضوحًا وصراحة في العادة.
</p>

<h2>
	الكلمة المفتاحية decltype الزائدة في قوالب الدوالّ
</h2>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	يمكن استخدام <code>‎decltype‎</code> زائدة (trailing) لتحديد نوع القيمة المُعادة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1717_51" style="">
<span class="kwd">namespace</span><span class="pln"> details
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">to_string</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// to_string(T) ينبغي أن تكون قادرة على استدعاء</span><span class="pln">
    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">auto</span><span class="pln"> convert_to_string</span><span class="pun">(</span><span class="pln">T </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> val</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">)-&gt;</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">to_string</span><span class="pun">(</span><span class="pln">val</span><span class="pun">))</span><span class="pln">

        </span><span class="pun">}</span><span class="pln">

   </span><span class="com">// ellipsis argument هذه غير مقيّدة، لكن يُفضَّل عدم استخدامها بسبب وسيط علامة الحذف</span><span class="pln">
    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">string convert_to_string</span><span class="pun">(</span><span class="pln">T </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> val</span><span class="pun">,</span><span class="pln"> </span><span class="pun">...</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">ostringstream oss</span><span class="pun">;</span><span class="pln">
            oss </span><span class="pun">&lt;&lt;</span><span class="pln"> val</span><span class="pun">;</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> oss</span><span class="pun">.</span><span class="pln">str</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">string convert_to_string</span><span class="pun">(</span><span class="pln">T </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> val</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> details</span><span class="pun">::</span><span class="pln">convert_to_string</span><span class="pun">(</span><span class="pln">val</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	في حال استدعاء <code>‎convert_to_string()‎</code> باستخدام وسيط يمكن استدعاء الدالة <code>‎to_string()‎</code> من خلاله، فعندها ستكون لدينا دالتان قابلتان للتطبيق على <code>‎details::convert_to_string()‎</code>، والأولى مُفضّلة لأنّ تسلسل التحويل الضمني من <code>‎0‎</code> إلى <code>‎int‎</code> أفضل من التحويل من <code>‎0‎</code> إلى <code>‎...‎</code>
</p>

<p>
	أما في حال استدعاء <code>‎convert_to_string()‎</code> باستخدام وسيط لا يمكننا عبره استدعاء <code>‎to_string()‎</code>، فحينئذٍ سيؤدّي استنساخ قالب الدالة الأوّل إلى فشل الاستبدال - substitution failure - (ليس هناك <code>‎decltype(to_string(val))‎</code>)، ونتيجة لذلك، يُزال هذا المرشح من مجموعة التحميل الزائد. قالب الدالّة الثاني غير مقيّد ولذا تم اختياره، وسنمرّ عبر <code>‎operator&lt;&lt;(std::ostream&amp;, T)‎</code>، أمّا في حال لم يكن معرَّفًا فسيحدث خطأ فادح في التصريف لمكدّس القالب (template stack) في سطر <code>‎oss &lt;&lt; val‎</code>.
</p>

<h2>
	enable<em>if</em>all / enable<em>if</em>any
</h2>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<h3>
	مثال تحفيزي
</h3>

<p>
	لدينا في الشيفرة التالية حزمة قالب متغيّرة (variadic template pack) في قائمة معاملات القالب:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1717_53" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pun">...</span><span class="typ">Args</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">(</span><span class="typ">Args</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">...</span><span class="pln">args</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">//... };</span></pre>

<p>
	لا تعطينا المكتبة القياسية (قبل الإصدار C++‎ 17) أيّ طريقة مباشرة لكتابة <code>enable_if</code> لفرض قيود قاعدة SFINAE على جميع (أو أيٍّ من) المعاملات في <code>‎Args‎</code>. توفّر C++‎ 17 حلّين لهذه المشكلة، وهما: <code>‎std::conjunction‎</code> و <code>‎std::disjunction‎</code>. انظر المثال التالي: قيود SFINAE على جميع المعامِلات في <code>Args</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1717_55" style="">
<span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> </span><span class="pun">...</span><span class="typ">Args</span><span class="pun">,</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">enable_if_t</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">conjunction_v</span><span class="pun">&lt;</span><span class="pln">custom_conditions_v</span><span class="pun">&lt;</span><span class="typ">Args</span><span class="pun">&gt;...&gt;&gt;*</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">nullptr</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">(</span><span class="typ">Args</span><span class="pln"> </span><span class="pun">&amp;&amp;...</span><span class="pln">args</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">//... };</span><span class="pln">

</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> </span><span class="pun">...</span><span class="typ">Args</span><span class="pun">,</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">enable_if_t</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">disjunction_v</span><span class="pun">&lt;</span><span class="pln">custom_conditions_v</span><span class="pun">&lt;</span><span class="typ">Args</span><span class="pun">&gt;...&gt;&gt;*</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">nullptr</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">(</span><span class="typ">Args</span><span class="pln"> </span><span class="pun">&amp;&amp;...</span><span class="pln">args</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">//... };</span></pre>

<p>
	إذا كنت تعمل بإصدار أقل من C++‎ 17، فهناك العديد من الحلول الممكنة لتحقيق ذلك، أحدها هو استخدام صنف الحالة الأساسية (base-case class) والتخصيصات الجزئية، كما هو مُوضّح في <a data-ss1617022796="1" href="https://stackoverflow.com/questions/26421104/how-do-i-enable-if-a-class-with-variadic-template-arguments" rel="external nofollow">جواب هذا السؤال</a>.
</p>

<p>
	يمكن أيضًا تنفيذ سلوك <code>‎std::conjunction‎</code> و <code>‎std::disjunction‎</code> بطريقة مباشرة، وسأوضح في المثال التالي، كيفيّة كتابة التنفيذات وسأجمعها مع <code>std::enable_if</code> لإنتاج كُنيتين: <code>‎enable_if_all‎</code> و <code>‎enable_if_any‎</code>، واللّتان تفعلان بالضبط ما يفترض بهما فعله. قد يكون هذا الحلّ أكثر قابلية للتوسيع.
</p>

<h3>
	تطبيق <code>‎enable_if_all‎</code> و <code>‎enable_if_any‎</code>
</h3>

<p>
	أولاً، سنحاكي <code>‎std::conjunction‎</code> و <code>‎std::disjunction‎</code> باستخدام <code>‎seq_and‎</code> و <code>‎seq_or‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1717_57" style="">
<span class="com">/// C++14 مساعد لاستخدامه في الإصدارات التي تسبق</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">bool</span><span class="pln"> B</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> F </span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">conditional_t</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">conditional</span><span class="pun">&lt;</span><span class="pln">B</span><span class="pun">,</span><span class="pln">T</span><span class="pun">,</span><span class="pln">F</span><span class="pun">&gt;::</span><span class="pln">type</span><span class="pun">;</span><span class="pln">
</span><span class="com">/// Emulate C++17 std::conjunction.</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">bool</span><span class="pun">...&gt;</span><span class="pln"> </span><span class="kwd">struct</span><span class="pln"> seq_or</span><span class="pun">:</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">false_type </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">bool</span><span class="pun">...&gt;</span><span class="pln"> </span><span class="kwd">struct</span><span class="pln"> seq_and</span><span class="pun">:</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">true_type </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">bool</span><span class="pln"> B1</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">bool</span><span class="pun">...</span><span class="pln"> </span><span class="typ">Bs</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> seq_or</span><span class="pun">&lt;</span><span class="pln">B1</span><span class="pun">,</span><span class="typ">Bs</span><span class="pun">...&gt;:</span><span class="pln">
    </span><span class="typ">conditional_t</span><span class="pun">&lt;</span><span class="pln">B1</span><span class="pun">,</span><span class="pln">std</span><span class="pun">::</span><span class="pln">true_type</span><span class="pun">,</span><span class="pln">seq_or</span><span class="pun">&lt;</span><span class="typ">Bs</span><span class="pun">...&gt;&gt;</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">bool</span><span class="pln"> B1</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">bool</span><span class="pun">...</span><span class="pln"> </span><span class="typ">Bs</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> seq_and</span><span class="pun">&lt;</span><span class="pln">B1</span><span class="pun">,</span><span class="typ">Bs</span><span class="pun">...&gt;:</span><span class="pln">
    </span><span class="typ">conditional_t</span><span class="pun">&lt;</span><span class="pln">B1</span><span class="pun">,</span><span class="pln">seq_and</span><span class="pun">&lt;</span><span class="typ">Bs</span><span class="pun">...&gt;,</span><span class="pln">std</span><span class="pun">::</span><span class="pln">false_type</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{};</span></pre>

<p>
	الآن سيصبح التنفيذ واضحًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1717_59" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">bool</span><span class="pun">...</span><span class="typ">Bs</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> enable_if_any </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">enable_if</span><span class="pun">&lt;</span><span class="pln">seq_or </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Bs</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;::</span><span class="pln">value </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">bool</span><span class="pun">...</span><span class="typ">Bs</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> enable_if_all </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">enable_if</span><span class="pun">&lt;</span><span class="pln">seq_and </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Bs</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;::</span><span class="pln">value </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">;</span></pre>

<p>
	وأخيرًا بعض المساعِدات:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1717_61" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">bool</span><span class="pun">...</span><span class="typ">Bs</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> </span><span class="typ">enable_if_any_t</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> enable_if_any </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Bs</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;::</span><span class="pln">type</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">bool</span><span class="pun">...</span><span class="typ">Bs</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> </span><span class="typ">enable_if_all_t</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> enable_if_all </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Bs</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;::</span><span class="pln">type</span><span class="pun">;</span></pre>

<h3>
	كيفية الاستخدام
</h3>

<p>
	الاستخدام واضح ومباشر: قيود SFINAE على جميع المعامِلات في <code>Args</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1717_63" style="">
<span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> </span><span class="pun">...</span><span class="typ">Args</span><span class="pun">,</span><span class="pln">
</span><span class="typ">enable_if_all_t</span><span class="pun">&lt;</span><span class="pln">custom_conditions_v</span><span class="pun">&lt;</span><span class="typ">Args</span><span class="pun">&gt;...&gt;*</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">nullptr</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">(</span><span class="typ">Args</span><span class="pln"> </span><span class="pun">&amp;&amp;...</span><span class="pln">args</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">//... };</span><span class="pln">

</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> </span><span class="pun">...</span><span class="typ">Args</span><span class="pun">,</span><span class="pln">
</span><span class="typ">enable_if_any_t</span><span class="pun">&lt;</span><span class="pln">custom_conditions_v</span><span class="pun">&lt;</span><span class="typ">Args</span><span class="pun">&gt;...&gt;*</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">nullptr</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">(</span><span class="typ">Args</span><span class="pln"> </span><span class="pun">&amp;&amp;...</span><span class="pln">args</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">//... };</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617022796="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 103: SFINAE (Substitution Failure Is Not An Error)‎ من كتاب <a data-ss1617022796="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">1021</guid><pubDate>Fri, 09 Oct 2020 13:07:00 +0000</pubDate></item><item><title>&#x645;&#x648;&#x627;&#x636;&#x64A;&#x639; &#x645;&#x62A;&#x642;&#x62F;&#x645;&#x629; &#x639;&#x646; &#x627;&#x644;&#x623;&#x646;&#x648;&#x627;&#x639; &#x648;&#x627;&#x644;&#x62A;&#x639;&#x627;&#x645;&#x644; &#x645;&#x639;&#x647;&#x627; &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D9%85%D9%88%D8%A7%D8%B6%D9%8A%D8%B9-%D9%85%D8%AA%D9%82%D8%AF%D9%85%D8%A9-%D8%B9%D9%86-%D8%A7%D9%84%D8%A3%D9%86%D9%88%D8%A7%D8%B9-%D9%88%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9%D9%87%D8%A7-%D9%81%D9%8A-cpp-r974/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_08/45.png.5862095ee8c631cd97fe6a5c9cabc221.png" /></p>

<h2>
	آلية RTTI: معلومات الأنواع في وقت التشغيل (Run-Time Type Information)
</h2>

<h3>
	dynamic_cast
</h3>

<p>
	استخدم <code>‎dynamic_cast&lt;&gt;()‎</code> كدالة تساعدك على التخفيض النوعي (downcasting) في التسلسل الهرمي للوراثة (الوصف الرئيسي). وإذا كنت بحاجة إلى إجراء بعض الأعمال غير <a data-ss1617022768="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-16-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-%D8%A7%D9%84%D8%AA%D8%B9%D8%AF%D8%AF%D9%8A%D8%A9-%D8%A7%D9%84%D8%B4%D9%83%D9%84%D9%8A%D8%A9-polymorphism-%D9%81%D9%8A-cpp-r900/" rel="">متعددة الأشكال</a> (non-polymorphic) على صنفين مشتقّين <code>‎B‎</code> و <code>‎C‎</code> عبر الصنف الأب <code>‎class A‎</code>، فستحتاج إلى كتابة ما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_7" style="">
<span class="kwd">class</span><span class="pln"> A </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">public</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">virtual</span><span class="pln"> </span><span class="pun">~</span><span class="pln">A</span><span class="pun">(){}</span><span class="pln"> </span><span class="pun">};</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> B</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> A
</span><span class="pun">{</span><span class="pln"> </span><span class="kwd">public</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> work4B</span><span class="pun">(){}</span><span class="pln"> </span><span class="pun">};</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> C</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> A
</span><span class="pun">{</span><span class="pln"> </span><span class="kwd">public</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> work4C</span><span class="pun">(){}</span><span class="pln"> </span><span class="pun">};</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> non_polymorphic_work</span><span class="pun">(</span><span class="pln">A</span><span class="pun">*</span><span class="pln"> ap</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">B</span><span class="pun">*</span><span class="pln"> bp </span><span class="pun">=</span><span class="kwd">dynamic_cast</span><span class="pun">&lt;</span><span class="pln">B</span><span class="pun">*&gt;(</span><span class="pln">ap</span><span class="pun">))</span><span class="pln">
        bp</span><span class="pun">-&gt;</span><span class="pln">work4B</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">C</span><span class="pun">*</span><span class="pln"> cp </span><span class="pun">=</span><span class="kwd">dynamic_cast</span><span class="pun">&lt;</span><span class="pln">C</span><span class="pun">*&gt;(</span><span class="pln">ap</span><span class="pun">))</span><span class="pln">
        cp</span><span class="pun">-&gt;</span><span class="pln">work4C</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	الكلمة المفتاحية typeid
</h3>

<p>
	الكلمة المفتاحية <code>‎typeid‎</code> هي عامل أحادي يعطي معلومات حول النوع المُمرّر إليها في وقت التشغيل في حال كان معامَلها (operand) كائنًا من صنف متعدد الأشكال. تعيد <code>‎typeid‎</code> <a data-ss1617022768="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-40-%D9%81%D8%A6%D8%A7%D8%AA-%D8%A7%D9%84%D9%82%D9%8A%D9%85-value-categories-%D9%81%D9%8A-cpp-r969/" rel="">قيمةً يسارية</a> من النوع <code>‎const std::type_info‎</code>، كما تتجاهَل التأهيل عالي المستوى (Top-level cv-qualiﬁcation).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_9" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Base</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pun">~</span><span class="typ">Base</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Derived</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="typ">Base</span><span class="pln"> </span><span class="pun">*</span><span class="pln">b </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Derived</span><span class="pun">;</span><span class="pln">
assert</span><span class="pun">(</span><span class="kwd">typeid</span><span class="pun">(*</span><span class="pln">b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="kwd">typeid</span><span class="pun">(</span><span class="typ">Derived</span><span class="pln"> </span><span class="pun">{}));</span><span class="pln">    </span><span class="com">// حسنا</span></pre>

<p>
	يمكن أيضًا تطبيق <code>‎typeid‎</code> على النوع مباشرة، ويتم تجريد مراجع المستوى الأعلى الأولى (first top-level references) في هذه الحالة، ثم يُتجاهَل التأهيل عالي المستوى. ومن ثم يمكن كتابة المثال أعلاه باستخدام <code>‎typeid(Derived)‎</code> بدلاً من <code>typeid(Derived{})‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_11" style="">
<span class="pln">assert</span><span class="pun">(</span><span class="kwd">typeid</span><span class="pun">(*</span><span class="pln">b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="kwd">typeid</span><span class="pun">(</span><span class="typ">Derived</span><span class="pln"> </span><span class="pun">{}));</span><span class="pln">    </span><span class="com">// OK</span></pre>

<p>
	إذا طُبِّقت <code>‎typeid‎</code> على تعبير من غير النوع متعدد الأشكال فلن يُقيَّم المعامَل، أمّا معلومات النوع المُعادة فستخصّ النوع الساكن.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_13" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Base</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// ملاحظة: لا مدمّرات وهمية</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Derived</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="typ">Derived</span><span class="pln"> d</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Base</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">b </span><span class="pun">=</span><span class="pln"> d</span><span class="pun">;</span><span class="pln">
assert</span><span class="pun">(</span><span class="kwd">typeid</span><span class="pun">(</span><span class="pln">b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="kwd">typeid</span><span class="pun">(</span><span class="typ">Base</span><span class="pun">));</span><span class="pln">    </span><span class="com">// غير مشتق</span><span class="pln">
assert</span><span class="pun">(</span><span class="kwd">typeid</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">declval</span><span class="pun">&lt;</span><span class="typ">Base</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">())</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="kwd">typeid</span><span class="pun">(</span><span class="typ">Base</span><span class="pun">));</span><span class="pln">    </span><span class="com">// لابأس، لأنّه غير مُقيَّم</span></pre>

<h3>
	أسماء الأنواع
</h3>

<p>
	تستطيع الحصول على الاسم المعرَّف من قِبل التنفيذ لنوع معيّن في وقت التشغيل باستخدام الدالة التابعة <code>‎.name()‎</code> الخاص بالكائن <code>‎std::type_info‎</code> المُعاد من قِبل <code>‎typeid‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_15" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;typeinfo&gt;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> speed </span><span class="pun">=</span><span class="pln"> </span><span class="lit">110</span><span class="pun">;</span><span class="pln">

    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="kwd">typeid</span><span class="pun">(</span><span class="pln">speed</span><span class="pun">).</span><span class="pln">name</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يكون الخرج ما يلي (متعلق بالتنفيذ):
</p>

<pre class="ipsCode">
int
</pre>

<h3>
	كيف تعرّف التحويل الذي ينبغي استخدامه
</h3>

<ul>
<li>
		<p>
			استخدم <strong>التحويل الديناميكي</strong> dynamic_cast لتحويل المؤشّرات/المراجع داخل التسلسل الهرمي للوراثة.
		</p>
	</li>
	<li>
		<p>
			استخدم <strong>التحويل الساكن</strong> static_cast لإجراء تحويلات الأنواع العادية.
		</p>
	</li>
	<li>
		<p>
			استخدم <strong>تحويل إعادة التفسير</strong> reinterpret_cast لإعادة تفسير أنماط البتات منخفضة المستوى، لكن استخدمه بحذر شديد.
		</p>
	</li>
	<li>
		<p>
			استخدم <strong>التحويل الثابت</strong> const_cast للتخلص من الثباتيّة أو التغايرية (const/volatile). تجنّب هذا الخيار ولا تستخدمه إلّا كنت مضطرًّا لاستخدام واجهة برمجية غير صحيحة ثباتيًّا (const-incorrect <abbr title="Application Programming Interface | واجهة برمجية">API</abbr>).
		</p>
	</li>
</ul>
<h2>
	شطب الأنواع Type Erasure
</h2>

<p>
	شطب النوع (Type Erasure) هو مجموعة من التقنيات الهادفة لإنشاء نوع يمكن أن يوفّر واجهة موحّدة للأنواع الأساسية (underlying types)، مع إخفاء معلومات النوع الأساسي عن العميل. وتُعدُّ <code>‎std::function&lt;R(A...)&gt;‎</code>، التي يمكنها تخزين كائنات قابلة للاستدعاء من مختلف الأنواع، أفضل مثال معروف على شطب الأنواع في C++‎.
</p>

<h3>
	<code>std::function</code> للنقل فقط
</h3>

<p>
	شطب النوع <code>std::function</code> ينحصر في عدد قليل من العمليات، وأحد الأشياء التي يتطّلّبها الشطب أن تكون القيمة المخزّنة قابلة للنسخ. لكن هذا قد يتسبّب بمشاكل في بعض السياقات، كما في حالة تخزين <a data-ss1617022768="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-39-%D8%AF%D9%88%D8%A7%D9%84-%D9%84%D8%A7%D9%85%D8%AF%D8%A7-lambdas-%D9%81%D9%8A-cpp-r960/" rel="">تعابير لامبدا</a> للمؤشرات الحصريّة (unique ptrs)، وقد يضيف هذا المتطلَّب حِملًا إضافيًا على البرنامج إذا كنت تستخدم <code>‎std::function‎</code> في سياق لا يهمّ فيه النسخ، كساحة خيوط (thread pool) مثلًا، حيث توفد (dispatch) المهامّ إلى <a data-ss1617022768="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-43-%D8%A7%D9%84%D8%AE%D9%8A%D9%88%D8%B7-threading-%D9%81%D9%8A-cpp-r972/" rel="">الخيوط</a>.
</p>

<p>
	الكائن <code>‎std::packaged_task&lt;Sig&gt;‎</code> هو كائن قابل للاستدعاء، كما أنه قابل للنقل فقط (move-only)، وتستطيع تخزين <code>std::packaged_task&lt;R(Args...)&gt;‎</code> في <code>std::packaged_task&lt;void(Args...)&gt;‎</code>، إلا أنّها طريقة بطيئة لإنشاء صنف شطب للنوع (type-erasure class) يكون للنقل فقط (move-only) وقابلا للاستدعاء (callable) في نفس الوقت.
</p>

<p>
	يوضّح المثال التالي كيف يمكنك كتابة نوع <code>‎std::function‎</code> بسيط، سنحذف مُنشئ النسخ - copy constructor - (والذي يتضمّن إضافة تابع <code>‎clone‎</code> إلى <code>‎details::task_pimpl&lt;...&gt;‎</code>). سنضعه في فضاء اسم (namespace) إذ سيسمح لنا ذلك بتخصيصه للقيمة المعادة الفارغة <code>void</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_17" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Sig</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> task</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">namespace</span><span class="pln"> details
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> R</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="typ">Args</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">struct</span><span class="pln"> task_pimpl
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">virtual</span><span class="pln"> R invoke</span><span class="pun">(</span><span class="typ">Args</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">...</span><span class="pln">args</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
            </span><span class="kwd">virtual</span><span class="pun">~</span><span class="pln">task_pimpl</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
            </span><span class="kwd">virtual</span><span class="pln">
            </span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">type_info </span><span class="pun">&amp;</span><span class="pln">target_type</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">};</span><span class="pln">
    </span><span class="com">// store an F.    invoke(Args&amp;&amp;...) calls the f</span><span class="pln">
    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> F</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> R</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="typ">Args</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">struct</span><span class="pln"> task_pimpl_impl</span><span class="pun">:</span><span class="pln"> task_pimpl</span><span class="pun">&lt;</span><span class="pln">R</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Args</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            F f</span><span class="pun">;</span><span class="pln">
            </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Fin</span><span class="pun">&gt;</span><span class="pln">
            task_pimpl_impl</span><span class="pun">(</span><span class="typ">Fin</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> fin</span><span class="pun">):</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="typ">Fin</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">fin</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

            </span><span class="kwd">virtual</span><span class="pln"> R invoke</span><span class="pun">(</span><span class="typ">Args</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">...</span><span class="pln">args</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> final override
            </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="typ">Args</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">args</span><span class="pun">)...);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">

            </span><span class="kwd">virtual</span><span class="pln">
            </span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">type_info </span><span class="pun">&amp;</span><span class="pln">target_type</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> final override
            </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">typeid</span><span class="pun">(</span><span class="pln">F</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">};</span></pre>

<p>
	سيتجاهل إصدار <code>void</code> القيمة التي تعيدها <code>f</code>، نتابع …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_19" style="">
<span class="pln">    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> F</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="typ">Args</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">struct</span><span class="pln"> task_pimpl_impl</span><span class="pun">&lt;</span><span class="pln">F</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Args</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;:</span><span class="pln"> task_pimpl</span><span class="pun">&lt;</span><span class="kwd">void</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Args</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            F f</span><span class="pun">;</span><span class="pln">
            </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Fin</span><span class="pun">&gt;</span><span class="pln">
            task_pimpl_impl</span><span class="pun">(</span><span class="typ">Fin</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> fin</span><span class="pun">):</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="typ">Fin</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">fin</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

            </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> invoke</span><span class="pun">(</span><span class="typ">Args</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">...</span><span class="pln">args</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> final override
            </span><span class="pun">{</span><span class="pln">
                f</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="typ">Args</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">args</span><span class="pun">)...);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">

            </span><span class="kwd">virtual</span><span class="pln">
            </span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">type_info </span><span class="pun">&amp;</span><span class="pln">target_type</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> final override
            </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">typeid</span><span class="pun">(</span><span class="pln">F</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">};</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> R</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="typ">Args</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> task </span><span class="pun">&lt;</span><span class="pln"> R</span><span class="pun">(</span><span class="typ">Args</span><span class="pun">...)</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// semi-regular:</span><span class="pln">
        task</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
        task</span><span class="pun">(</span><span class="pln">task </span><span class="pun">&amp;&amp;)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
        </span><span class="com">// no copy</span><span class="pln">
        </span><span class="kwd">private</span><span class="pun">:</span></pre>

<p>
	هنا ننشئ أسماءً بديلة أو كُنى (aliases) لتحسين مظهر شيفرة sfinae أدناه، …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_21" style="">
<span class="pln">            </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> F</span><span class="pun">&gt;</span><span class="pln">
            </span><span class="kwd">using</span><span class="pln"> call_r </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">result_of_t</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> F
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;(</span><span class="typ">Args</span><span class="pun">...)</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> F</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> is_task </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">is_same</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="typ">decay_t</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> F</span><span class="pun">&gt;,</span><span class="pln"> task</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
            </span><span class="com">// قابل للاستدعاء F يمكن تدميرها من كائن </span><span class="pln">
            </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> F</span><span class="pun">,</span><span class="pln">

        </span><span class="kwd">class</span><span class="pun">=</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln"> </span><span class="pun">(</span><span class="pln">R</span><span class="pun">)(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">declval</span><span class="pun">&lt;</span><span class="pln">call_r</span><span class="pun">&lt;</span><span class="pln">F</span><span class="pun">&gt;&gt;())</span><span class="pln"> </span><span class="pun">),</span><span class="pln">
        </span><span class="com">// ليس النوع نفسه</span><span class="pln">
        std</span><span class="pun">::</span><span class="typ">enable_if_t</span><span class="pun">&lt;!</span><span class="pln">is_task</span><span class="pun">&lt;</span><span class="pln">F</span><span class="pun">&gt;{},</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&gt;*</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">nullptr</span><span class="pun">&gt;</span><span class="pln">
        task</span><span class="pun">(</span><span class="pln">F</span><span class="pun">&amp;&amp;</span><span class="pln"> f</span><span class="pun">):</span><span class="pln">m_pImpl</span><span class="pun">(</span><span class="pln"> make_pimpl</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="pln">F</span><span class="pun">&gt;(</span><span class="pln">f</span><span class="pun">))</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">


        R </span><span class="kwd">operator</span><span class="pun">()(</span><span class="typ">Args</span><span class="pun">...</span><span class="pln">args</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> m_pImpl</span><span class="pun">-&gt;</span><span class="pln">invoke</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="typ">Args</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">args</span><span class="pun">)...);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">explicit</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="kwd">bool</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">bool</span><span class="pun">)</span><span class="pln"> m_pImpl</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">void</span><span class="pln"> swap</span><span class="pun">(</span><span class="pln">task </span><span class="pun">&amp;</span><span class="pln"> o</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">swap</span><span class="pun">(</span><span class="pln">m_pImpl</span><span class="pun">,</span><span class="pln"> o</span><span class="pun">.</span><span class="pln">m_pImpl</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> F</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> assign</span><span class="pun">(</span><span class="pln">F </span><span class="pun">&amp;&amp;</span><span class="pln"> f</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            m_pImpl </span><span class="pun">=</span><span class="pln"> make_pimpl</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="pln">F</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">f</span><span class="pun">));</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="com">// std::function جزء من واجهة</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">type_info </span><span class="pun">&amp;</span><span class="pln">target_type</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">typeid</span><span class="pun">(</span><span class="kwd">void</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> m_pImpl</span><span class="pun">-&gt;</span><span class="pln">target_type</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
        T</span><span class="pun">*</span><span class="pln"> target</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> target_impl</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> T</span><span class="pun">*</span><span class="pln"> target</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> target_impl</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="com">// nullptr مقارنة مع</span><span class="pln">
        </span><span class="kwd">friend</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">==(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">nullptr_t</span><span class="pun">,</span><span class="pln"> task
            </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">!</span><span class="pln">self</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">friend</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">==(</span><span class="pln">task
            </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">nullptr_t</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">!</span><span class="pln">self</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">friend</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">!=(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">nullptr_t</span><span class="pun">,</span><span class="pln"> task
            </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">!!</span><span class="pln">self</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">friend</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">!=(</span><span class="pln">task
            </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">nullptr_t</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">!!</span><span class="pln">self</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">private</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
            </span><span class="kwd">using</span><span class="pln"> </span><span class="typ">pimpl_t</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> details</span><span class="pun">::</span><span class="pln">task_pimpl_impl</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> R</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Args</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> F</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> make_pimpl</span><span class="pun">(</span><span class="pln">F </span><span class="pun">&amp;&amp;</span><span class="pln"> f</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">using</span><span class="pln"> dF </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">decay_t</span><span class="pun">&lt;</span><span class="pln">F</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
            </span><span class="kwd">using</span><span class="pln"> </span><span class="typ">pImpl_t</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">pimpl_t</span><span class="str">&lt;dF&gt;</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_unique</span><span class="str">&lt;pImpl_t&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="pln">F</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">f</span><span class="pun">));</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        std</span><span class="pun">::</span><span class="pln">unique_ptr</span><span class="pun">&lt;</span><span class="pln">details</span><span class="pun">::</span><span class="pln">task_pimpl</span><span class="pun">&lt;</span><span class="pln">R</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Args</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;&gt;</span><span class="pln"> m_pImpl</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
        T</span><span class="pun">*</span><span class="pln"> target_impl</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">dynamic_cast</span><span class="pun">&lt;</span><span class="typ">pimpl_t</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">*&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">m_pImpl</span><span class="pun">.</span><span class="pln">get</span><span class="pun">());</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span></pre>

<p>
	ربما تود إضافة تحسين للمخزن المؤقت الصغير (Small Buffer Optimization) لهذه المكتبة كي لا تخزِّن كل الاستدعاءات في الكومة (heap). وستجد أنك محتاج إلى استخدام <code>‎task(task&amp;&amp;)‎</code> غير الافتراضية من أجل إضافة ذلك التحسين، كذلك ستحتاج إلى <code>‎std::aligned_storage_t‎</code> داخل الصنف، ومؤشّر حصري <code>‎unique_ptr‎</code> يشير إلى <code>‎m_pImpl‎</code> مع حاذف (deleter) يمكن ضبطه على خاصّية التدمير فقط (مع عدم إعادة الذاكرة إلى الكومة). أيضًا، ستحتاج إلى كتابة <code>emplace_move_to( void* ) = 0‎</code> في <code>‎task_pimpl‎</code>.
</p>

<p>
	انظر <a data-ss1617022768="1" href="http://coliru.stacked-crooked.com/a/6e6811e8626a37d1" rel="external nofollow">هذا المثال الحي</a> (بدون خوارزمية تحسين المخزن المؤقت الصغير SBO).
</p>

<h3>
	الشطب إلى نوع نمطي مع جدول (vtable) وهمي
</h3>

<p>
	تعتمد C++‎ على ما يُعرف بالأنواع النمطية - Regular types - (أو على الأقل شبه النمطية - Pseudo-Regular). والنوع النمطي هو نوع يمكن إنشاؤه والإسناد إليه أو منه عبر النسخ أو النقل، ويمكن تدميره، ويمكن مقارنته عبر معامل المساواة. ويمكن أيضًا أن يُنشأ بدون وسائط، كما يدعم بعض العمليات الأخرى المفيدة في خوارزميات وحاويات المكتبة القياسية <code>‎std‎</code>.
</p>

<p>
	اطلع إن شئت على <a data-ss1617022768="1" href="http://stepanovpapers.com/DeSt98.pdf" rel="external nofollow">هذا الرابط الأجنبي إلى الورقة الأصلية</a> التي تأسس عليها هذا المفهوم. قد ترغب في إضافة دعم لـ <code>‎std::hash‎</code> في C++‎ 11.
</p>

<p>
	وهنا، سنستخدم منهج الجدول الوهمي vtable لأجل شطب النوع (type erasure).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_23" style="">
<span class="kwd">using</span><span class="pln"> dtor_unique_ptr </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">unique_ptr</span><span class="pun">&lt;</span><span class="kwd">void</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">(*)(</span><span class="kwd">void</span><span class="pun">*)</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="typ">Args</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    dtor_unique_ptr make_dtor_unique_ptr</span><span class="pun">(</span><span class="typ">Args</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">...</span><span class="pln">args</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">new</span><span class="pln"> T</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="typ">Args</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">args</span><span class="pun">)...),</span><span class="pln"> </span><span class="pun">[](</span><span class="kwd">void</span><span class="pln"> </span><span class="pun">*</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">delete</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">*&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">self</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">};</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> regular_vtable
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pun">(*</span><span class="pln">copy_assign</span><span class="pun">)(</span><span class="kwd">void</span><span class="pln"> </span><span class="pun">*</span><span class="pln">dest</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">void</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">*</span><span class="pln">src</span><span class="pun">);</span><span class="pln">    </span><span class="com">// T&amp;=(T const&amp;)</span><span class="pln">
    </span><span class="kwd">void</span><span class="pun">(*</span><span class="pln">move_assign</span><span class="pun">)(</span><span class="kwd">void</span><span class="pln"> </span><span class="pun">*</span><span class="pln">dest</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="pun">*</span><span class="pln">src</span><span class="pun">);</span><span class="pln">    </span><span class="com">// T&amp;=(T&amp;&amp;)</span><span class="pln">
    </span><span class="kwd">bool</span><span class="pun">(*</span><span class="pln">equals</span><span class="pun">)(</span><span class="kwd">void</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">*</span><span class="pln">lhs</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">void</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">*</span><span class="pln">rhs</span><span class="pun">);</span><span class="pln">    </span><span class="com">// T const&amp;==T const&amp;</span><span class="pln">
    </span><span class="kwd">bool</span><span class="pun">(*</span><span class="pln">order</span><span class="pun">)(</span><span class="kwd">void</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">*</span><span class="pln">lhs</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">void</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">*</span><span class="pln">rhs</span><span class="pun">);</span><span class="pln">    </span><span class="com">// std::less&lt;T&gt;{}(T const&amp;, T const&amp;)</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pun">(*</span><span class="pln">hash</span><span class="pun">)(</span><span class="kwd">void</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">*</span><span class="pln">self</span><span class="pun">);</span><span class="pln">    </span><span class="com">// std::hash&lt;T&gt;{}(T const&amp;)</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">type_info </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;(*</span><span class="pln">type</span><span class="pun">)();</span><span class="pln">    </span><span class="com">// typeid(T)</span><span class="pln">
    dtor_unique_ptr</span><span class="pun">(*</span><span class="pln">clone</span><span class="pun">)(</span><span class="kwd">void</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">*</span><span class="pln">self</span><span class="pun">);</span><span class="pln">    </span><span class="com">// T(T const&amp;)</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    regular_vtable make_regular_vtable</span><span class="pun">()</span><span class="pln"> noexcept
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="pun">[](</span><span class="kwd">void</span><span class="pln"> </span><span class="pun">*</span><span class="pln">dest</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">void</span><span class="pln">
                </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">*</span><span class="pln">src</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{*</span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">*&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">dest</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="pln"> T
                </span><span class="kwd">const</span><span class="pun">*&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">src</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">},</span><span class="pln">
        </span><span class="pun">[](</span><span class="kwd">void</span><span class="pln"> </span><span class="pun">*</span><span class="pln">dest</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="pun">*</span><span class="pln">src</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{*</span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">*&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">dest</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(*</span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">*&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">src</span><span class="pun">));</span><span class="pln">
            </span><span class="pun">},</span><span class="pln">
        </span><span class="pun">[](</span><span class="kwd">void</span><span class="pln">
                </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">*</span><span class="pln">lhs</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">void</span><span class="pln">
                </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">*</span><span class="pln">rhs</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="pln"> T
                </span><span class="kwd">const</span><span class="pun">*&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">lhs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="pln"> T
                </span><span class="kwd">const</span><span class="pun">*&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">rhs</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">},</span><span class="pln">
        </span><span class="pun">[](</span><span class="kwd">void</span><span class="pln">
                </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">*</span><span class="pln">lhs</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">void</span><span class="pln">
                </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">*</span><span class="pln">rhs</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">less </span><span class="pun">&lt;</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{}(*</span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="pln"> T
                    </span><span class="kwd">const</span><span class="pun">*&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">lhs</span><span class="pun">),</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="pln"> T
                    </span><span class="kwd">const</span><span class="pun">*&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">rhs</span><span class="pun">));</span><span class="pln">
            </span><span class="pun">},</span><span class="pln">
        </span><span class="pun">[](</span><span class="kwd">void</span><span class="pln">
                </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">*</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">hash </span><span class="pun">&lt;</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{}(*</span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="pln"> T
                    </span><span class="kwd">const</span><span class="pun">*&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">self</span><span class="pun">));</span><span class="pln">
            </span><span class="pun">},</span><span class="pln">
        </span><span class="pun">[]()-&gt;</span><span class="kwd">decltype</span><span class="pun">(</span><span class="kwd">auto</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">typeid</span><span class="pun">(</span><span class="pln">T</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">},</span><span class="pln">
        </span><span class="pun">[](</span><span class="kwd">void</span><span class="pln">
                </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">*</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> make_dtor_unique_ptr</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(*</span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="pln"> T
                    </span><span class="kwd">const</span><span class="pun">*&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">self</span><span class="pun">));</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">};</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    regular_vtable
</span><span class="kwd">const</span><span class="pun">*</span><span class="pln"> get_regular_vtable</span><span class="pun">()</span><span class="pln"> noexcept
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> regular_vtable vtable </span><span class="pun">=</span><span class="pln"> make_regular_vtable</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">vtable</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> regular_type
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> self </span><span class="pun">=</span><span class="pln"> regular_type</span><span class="pun">;</span><span class="pln">
    regular_vtable
    </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">*</span><span class="pln">vtable </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
    dtor_unique_ptr ptr
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">nullptr</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[](</span><span class="kwd">void</span><span class="pun">*)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">

    </span><span class="kwd">bool</span><span class="pln"> empty</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">!</span><span class="pln">vtable</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="typ">Args</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> emplace</span><span class="pun">(</span><span class="typ">Args</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">...</span><span class="pln">args</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            ptr </span><span class="pun">=</span><span class="pln"> make_dtor_unique_ptr</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="typ">Args</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">args</span><span class="pun">)...);</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">ptr</span><span class="pun">)</span><span class="pln">
                vtable </span><span class="pun">=</span><span class="pln"> get_regular_vtable</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">();</span><span class="pln">
            </span><span class="kwd">else</span><span class="pln">
                vtable </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">nullptr</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">friend</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">==(</span><span class="pln">regular_type
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">lhs</span><span class="pun">,</span><span class="pln"> regular_type
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">rhs</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">lhs</span><span class="pun">.</span><span class="pln">vtable </span><span class="pun">!=</span><span class="pln"> rhs</span><span class="pun">.</span><span class="pln">vtable</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> lhs</span><span class="pun">.</span><span class="pln">vtable</span><span class="pun">-&gt;</span><span class="pln">equals</span><span class="pun">(</span><span class="pln">lhs</span><span class="pun">.</span><span class="pln">ptr</span><span class="pun">.</span><span class="pln">get</span><span class="pun">(),</span><span class="pln"> rhs</span><span class="pun">.</span><span class="pln">ptr</span><span class="pun">.</span><span class="pln">get</span><span class="pun">());</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">bool</span><span class="pln"> before</span><span class="pun">(</span><span class="pln">regular_type
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">rhs</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">auto</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">lhs </span><span class="pun">=</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">lhs</span><span class="pun">.</span><span class="pln">vtable </span><span class="pun">||</span><span class="pln"> </span><span class="pun">!</span><span class="pln">rhs</span><span class="pun">.</span><span class="pln">vtable</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">less </span><span class="pun">&lt;</span><span class="pln"> regular_vtable
        </span><span class="kwd">const</span><span class="pun">*&gt;</span><span class="pln"> </span><span class="pun">{}(</span><span class="pln">lhs</span><span class="pun">.</span><span class="pln">vtable</span><span class="pun">,</span><span class="pln"> rhs</span><span class="pun">.</span><span class="pln">vtable</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">lhs</span><span class="pun">.</span><span class="pln">vtable </span><span class="pun">!=</span><span class="pln"> rhs</span><span class="pun">.</span><span class="pln">vtable</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> lhs</span><span class="pun">.</span><span class="pln">vtable</span><span class="pun">-&gt;</span><span class="pln">type</span><span class="pun">().</span><span class="pln">before</span><span class="pun">(</span><span class="pln">rhs</span><span class="pun">.</span><span class="pln">vtable</span><span class="pun">-&gt;</span><span class="pln">type</span><span class="pun">());</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> lhs</span><span class="pun">.</span><span class="pln">vtable</span><span class="pun">-&gt;</span><span class="pln">order</span><span class="pun">(</span><span class="pln">lhs</span><span class="pun">.</span><span class="pln">ptr</span><span class="pun">.</span><span class="pln">get</span><span class="pun">(),</span><span class="pln"> rhs</span><span class="pun">.</span><span class="pln">ptr</span><span class="pun">.</span><span class="pln">get</span><span class="pun">());</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	من الناحية الفنية، فإن <code>&gt;friend bool operator</code> التي تستدعي <code>before</code> مطلوبة هنا، نتابع المثال …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_25" style="">
<span class="pln">    std</span><span class="pun">::</span><span class="pln">type_info
    </span><span class="kwd">const</span><span class="pun">*</span><span class="pln"> type</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">vtable</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">nullptr</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">vtable</span><span class="pun">-&gt;</span><span class="pln">type</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    regular_type</span><span class="pun">(</span><span class="pln">regular_type </span><span class="pun">&amp;&amp;</span><span class="pln"> o</span><span class="pun">):</span><span class="pln">
        vtable</span><span class="pun">(</span><span class="pln">o</span><span class="pun">.</span><span class="pln">vtable</span><span class="pun">),</span><span class="pln">
        ptr</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">o</span><span class="pun">.</span><span class="pln">ptr</span><span class="pun">))</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            o</span><span class="pun">.</span><span class="pln">vtable </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">nullptr</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">friend</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> swap</span><span class="pun">(</span><span class="pln">regular_type </span><span class="pun">&amp;</span><span class="pln">lhs</span><span class="pun">,</span><span class="pln"> regular_type </span><span class="pun">&amp;</span><span class="pln">rhs</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">swap</span><span class="pun">(</span><span class="pln">lhs</span><span class="pun">.</span><span class="pln">ptr</span><span class="pun">,</span><span class="pln"> rhs</span><span class="pun">.</span><span class="pln">ptr</span><span class="pun">);</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">swap</span><span class="pun">(</span><span class="pln">lhs</span><span class="pun">.</span><span class="pln">vtable</span><span class="pun">,</span><span class="pln"> rhs</span><span class="pun">.</span><span class="pln">vtable</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    regular_type </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pun">=(</span><span class="pln">regular_type </span><span class="pun">&amp;&amp;</span><span class="pln"> o</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">o</span><span class="pun">.</span><span class="pln">vtable </span><span class="pun">==</span><span class="pln"> vtable</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            vtable</span><span class="pun">-&gt;</span><span class="pln">move_assign</span><span class="pun">(</span><span class="pln">ptr</span><span class="pun">.</span><span class="pln">get</span><span class="pun">(),</span><span class="pln"> o</span><span class="pun">.</span><span class="pln">ptr</span><span class="pun">.</span><span class="pln">get</span><span class="pun">());</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">auto</span><span class="pln"> tmp </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">o</span><span class="pun">);</span><span class="pln">
        swap</span><span class="pun">(*</span><span class="kwd">this</span><span class="pun">,</span><span class="pln"> tmp</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    regular_type</span><span class="pun">(</span><span class="pln">regular_type
            </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">o</span><span class="pun">):</span><span class="pln">
        vtable</span><span class="pun">(</span><span class="pln">o</span><span class="pun">.</span><span class="pln">vtable</span><span class="pun">),</span><span class="pln">
        ptr</span><span class="pun">(</span><span class="pln">o</span><span class="pun">.</span><span class="pln">vtable </span><span class="pun">?</span><span class="pln"> o</span><span class="pun">.</span><span class="pln">vtable</span><span class="pun">-&gt;</span><span class="pln">clone</span><span class="pun">(</span><span class="pln">o</span><span class="pun">.</span><span class="pln">ptr</span><span class="pun">.</span><span class="pln">get</span><span class="pun">())</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> dtor_unique_ptr
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">nullptr</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[](</span><span class="kwd">void</span><span class="pun">*)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln"> </span><span class="pun">})</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">ptr </span><span class="pun">&amp;&amp;</span><span class="pln"> vtable</span><span class="pun">)</span><span class="pln"> vtable </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">nullptr</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

    regular_type </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pun">=(</span><span class="pln">regular_type
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">o</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">o</span><span class="pun">.</span><span class="pln">vtable </span><span class="pun">==</span><span class="pln"> vtable</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            vtable</span><span class="pun">-&gt;</span><span class="pln">copy_assign</span><span class="pun">(</span><span class="pln">ptr</span><span class="pun">.</span><span class="pln">get</span><span class="pun">(),</span><span class="pln"> o</span><span class="pun">.</span><span class="pln">ptr</span><span class="pun">.</span><span class="pln">get</span><span class="pun">());</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">auto</span><span class="pln"> tmp </span><span class="pun">=</span><span class="pln"> o</span><span class="pun">;</span><span class="pln">
        swap</span><span class="pun">(*</span><span class="kwd">this</span><span class="pun">,</span><span class="pln"> tmp</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> hash</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">vtable</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> vtable</span><span class="pun">-&gt;</span><span class="pln">hash</span><span class="pun">(</span><span class="pln">ptr</span><span class="pun">.</span><span class="pln">get</span><span class="pun">());</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">,</span><span class="pln">
       std</span><span class="pun">::</span><span class="typ">enable_if_t</span><span class="pun">&lt;!</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_same</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="typ">decay_t</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> T</span><span class="pun">&gt;,</span><span class="pln"> regular_type</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{},</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&gt;*</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">nullptr</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
        regular_type</span><span class="pun">(</span><span class="pln">T </span><span class="pun">&amp;&amp;</span><span class="pln"> t</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            emplace</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="typ">decay_t</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> T</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">t</span><span class="pun">));</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">namespace</span><span class="pln"> std
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">struct</span><span class="pln"> hash </span><span class="pun">&lt;</span><span class="pln"> regular_type</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">()(</span><span class="pln">regular_type
                </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">r</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> r</span><span class="pun">.</span><span class="pln">hash</span><span class="pun">();</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">};</span><span class="pln">
    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">struct</span><span class="pln"> less </span><span class="pun">&lt;</span><span class="pln"> regular_type</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">bool</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">()(</span><span class="pln">regular_type
                </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">lhs</span><span class="pun">,</span><span class="pln"> regular_type
                </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">rhs</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> lhs</span><span class="pun">.</span><span class="pln">before</span><span class="pun">(</span><span class="pln">rhs</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">};</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<a data-ss1617022768="1" href="http://coliru.stacked-crooked.com/a/28ef6be761012a81" rel="external nofollow">هذا مثال حيّ</a> على ذلك.
</p>

<p>
	يمكن استخدام مثل هذا النوع النمطي كمفتاح <a data-ss1617022768="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-30-%D8%A7%D9%84%D9%86%D9%88%D8%B9-stdmap-%D8%A7%D9%84%D9%82%D9%88%D8%A7%D9%85%D9%8A%D8%B3-%D9%81%D9%8A-cpp-r942/" rel="">لقاموس</a> <code>‎std::map‎</code> أو قاموس غير مرتب <code>‎std::unordered_map‎</code>، والذي يقبل أيّ كائن نمطي كمفتاح، وستكون قيم القاموس كائنات قابلة للنسخ. مثلًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_27" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">map</span><span class="pun">&lt;</span><span class="pln">regular_type</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">any</span><span class="pun">&gt;</span></pre>

<p>
	وعلى عكس <code>‎any‎</code>، فلا يحسِّن النوع النمطي <code>‎regular_type‎</code> الذي أنشأناه في المثال أعلاه الكائنات الصغيرة (small object optimization)، ولا يدعم استعادة البيانات الأصلية، لكنّ ليس من الصعب الحصول على النوع الأصلي على أيّ حال.
</p>

<p>
	يتطّلب تحسين الكائنات الصغيرة حفظ مخزن مؤقّت مُحاذَى (aligned storage buffer) داخل <code>‎regular_type‎</code>، وتعديل الحاذف <code>‎ptr‎</code> بحذر كي ندمر الكائن دون حذفه. وسنبدأ من <code>‎make_dtor_unique_ptr‎</code>، ونعلّمه كيفيّة تخزين البيانات في المخزن المؤقّت، ثمّ في الكومة (heap) إذا لم يكن هناك مُتّسع في المخزن المؤقّت.
</p>

<h3>
	الآلية الأساسية
</h3>

<p>
	شطب النوع طريقةٌ لإخفاء نوع الكائن عن الشيفرة التي تستخدمه، حتى لو لم يكن مشتقًّا من أحد الأصناف الأساسية الشائعة، ويوفّر جسرًا بين عوالم تعددية الأشكال الساكنة (static polymorphism)، إذ يجب أن يكون النوع معروفًا بشكل تام عند استخدام القوالب في وقت التصريف، لكن لا يلزم أن يكون مُصرّحًا ليتوافق مع واجهة معيّنة عند التعريف، وبين تعددية الأشكال الديناميكية، إذ لا يلزم أن يكون النوع معروفًا بشكل كامل في وقت التصريف عند استخدام الوراثة والدوال الوهميّة، لكن يجب التصريح بأنّه يتوافق مع واجهة معيّنة عند التعريف.
</p>

<p>
	توضّح الشيفرة التالية الآلية الأساسية لشطب النوع.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_29" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;ostream&gt;</span><span class="pln">

    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Printable</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
            </span><span class="typ">Printable</span><span class="pun">(</span><span class="pln">T value</span><span class="pun">):</span><span class="pln"> pValue</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Value</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">value</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="pun">~</span><span class="typ">Printable</span><span class="pun">()</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">delete</span><span class="pln"> pValue</span><span class="pun">;</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">void</span><span class="pln"> print</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ostream </span><span class="pun">&amp;</span><span class="pln">os</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            pValue</span><span class="pun">-&gt;</span><span class="pln">print</span><span class="pun">(</span><span class="pln">os</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
            </span><span class="typ">Printable</span><span class="pun">(</span><span class="typ">Printable</span><span class="pln">
                </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;)</span><span class="pln"> </span><span class="com">/*in C++1x: =delete */</span><span class="pln"> </span><span class="pun">;</span><span class="pln">    </span><span class="com">// not implemented غير منفَّذ</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">=(</span><span class="typ">Printable</span><span class="pln">
            </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;)</span><span class="pln"> </span><span class="com">/*in C++1x: =delete */</span><span class="pln"> </span><span class="pun">;</span><span class="pln">    </span><span class="com">//  غير منفَّذ</span><span class="pln">
        </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">ValueBase</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">virtual</span><span class="pun">~</span><span class="typ">ValueBase</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
            </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> print</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ostream </span><span class="pun">&amp;)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">};</span><span class="pln">
        </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
            </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Value</span><span class="pun">:</span><span class="pln"> </span><span class="typ">ValueBase</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="typ">Value</span><span class="pun">(</span><span class="pln">T
                    </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">t</span><span class="pun">):</span><span class="pln"> v</span><span class="pun">(</span><span class="pln">t</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

                </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> print</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ostream </span><span class="pun">&amp;</span><span class="pln">os</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
                </span><span class="pun">{</span><span class="pln">
                    os </span><span class="pun">&lt;&lt;</span><span class="pln"> v</span><span class="pun">;</span><span class="pln">
                </span><span class="pun">}</span><span class="pln">

                T v</span><span class="pun">;</span><span class="pln">
            </span><span class="pun">};</span><span class="pln">
        </span><span class="typ">ValueBase</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> pValue</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span></pre>

<p>
	وحده التعريف أعلاه من يلزم أن يكون مرئيًا في موقع الاستخدام، تمامًا كما في الأصناف الأساسية ذات الدوال الوهميّة. مثلا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_31" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> print_value</span><span class="pun">(</span><span class="typ">Printable</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">p</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    p</span><span class="pun">.</span><span class="pln">print</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لاحظ أنّ هذا ليس قالبًا، وإنّما دالة عادية لا يلزم التصريح عنها إلا في ملف الترويسة، ويمكن تعريفها في ملف تنفيذ (implementation ﬁle) على عكس القوالب، التي يجب أن يكون تعريفها مرئيًا في مكان الاستخدام. كذلك لا يلزم معرفة أي شيء عن <code>‎Printable‎</code> في تعريفات الأنواع الحقيقية (concrete types)، باستثناء أن يكون متوافقًا مع الواجهة كما هو الحال مع القوالب:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_33" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">MyType</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
ostream </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pun">&lt;&lt;(</span><span class="pln">ostream </span><span class="pun">&amp;</span><span class="pln">os</span><span class="pun">,</span><span class="pln"> </span><span class="typ">MyType</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">mc</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> os </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"MyType {"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> mc</span><span class="pun">.</span><span class="pln">i </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"}"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكننا الآن تمرير كائن من هذا الصنف إلى الدالّة المُعرَّفة أعلاه:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_35" style="">
<span class="typ">MyType</span><span class="pln"> foo </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="lit">42</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
print_value</span><span class="pun">(</span><span class="pln">foo</span><span class="pun">);</span></pre>

<h3>
	شطب النوع إلى مخزن مؤقّت متجاور يضمّ عناصر من النوع T
</h3>

<p>
	لا يستدعي شطبُ الأنواعِ الوراثةَ الوهمية بالضرورة أو تخصيصات الذاكرة أو حتى مؤشّرات الدوالّ، وما يميّزه أنّه يصف مجموعة من السلوكيات ويأخذ أيّ نوع يدعم تلك السلوكيات ويغلّفه، أمّا السلوكيات الأخرى التي تميّز ذلك النوع غير الموجودة في تلك المجموعة "فتُنسى" أو "تُشطب".
</p>

<p>
	تأخذ <code>‎array_view‎</code> مجالًا (range) أو نوع حاوية وتشطب كلّ شيء باستثناء حقيقة أنّه مخزن مؤقّت متجاور يحتوي عناصر من النوع <code>‎T‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_37" style="">
<span class="com">// SFINAE سمة مساعدة لقاعدة</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> </span><span class="typ">data_t</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">declval</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">().</span><span class="pln">data</span><span class="pun">());</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Src</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> compatible_data </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">integral_constant</span><span class="pun">&lt;</span><span class="kwd">bool</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">is_same</span><span class="pun">&lt;</span><span class="typ">data_t</span><span class="pun">&lt;</span><span class="typ">Src</span><span class="pun">&gt;,</span><span class="pln"> T</span><span class="pun">*&gt;</span><span class="pln"> </span><span class="pun">{}</span><span class="pln"> </span><span class="pun">||</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">is_same</span><span class="pun">&lt;</span><span class="typ">data_t</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Src</span><span class="pun">&gt;,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">remove_const_t</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">*&gt;</span><span class="pln"> </span><span class="pun">{}</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> array_view
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// نواة الصنف</span><span class="pln">
        T </span><span class="pun">*</span><span class="pln">b </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">nullptr</span><span class="pun">;</span><span class="pln">
        T </span><span class="pun">*</span><span class="pln">e </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">nullptr</span><span class="pun">;</span><span class="pln">
        T</span><span class="pun">*</span><span class="pln"> begin</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        T</span><span class="pun">*</span><span class="pln"> end</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> e</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="com">// توفير التوابع المتوقّعة من مجال متجاور</span><span class="pln">
        T</span><span class="pun">*</span><span class="pln"> data</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> begin</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">bool</span><span class="pln"> empty</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> begin</span><span class="pun">()</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> end</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> size</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> end</span><span class="pun">()</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> begin</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        T </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pun">[](</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> i</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> begin</span><span class="pun">()[</span><span class="pln">i</span><span class="pun">];</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        T </span><span class="pun">&amp;</span><span class="pln">front</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pun">*</span><span class="pln"> begin</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        T </span><span class="pun">&amp;</span><span class="pln">back</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*(</span><span class="pln">end</span><span class="pun">()</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="com">// مساعدات مفيدة لتوليد مجالات أخرى من هذا المجال بشكل سريع وآمن</span><span class="pln">
        array_view without_front</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            i </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">min</span><span class="pun">)(</span><span class="pln">i</span><span class="pun">,</span><span class="pln"> size</span><span class="pun">());</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                begin</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> i</span><span class="pun">,</span><span class="pln"> end</span><span class="pun">()</span><span class="pln">
            </span><span class="pun">};</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        array_view without_back</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            i </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">min</span><span class="pun">)(</span><span class="pln">i</span><span class="pun">,</span><span class="pln"> size</span><span class="pun">());</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                begin</span><span class="pun">(),</span><span class="pln"> end</span><span class="pun">()</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> i
            </span><span class="pun">};</span><span class="pln">
        </span><span class="pun">}</span></pre>

<p>
	<code>array_view</code> هو منسق بيانات بصيغة البيانات القديمة، لذا النسخة الافتراضية: …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_39" style="">
<span class="pln">        array_view</span><span class="pun">(</span><span class="pln">array_view
                </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
        </span><span class="com">// empty range توليد مجال فارغ</span><span class="pln">
        array_view</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
        </span><span class="com">// المنشئ النهائي</span><span class="pln">
        array_view</span><span class="pun">(</span><span class="pln">T </span><span class="pun">*</span><span class="pln">s</span><span class="pun">,</span><span class="pln"> T </span><span class="pun">*</span><span class="pln">f</span><span class="pun">):</span><span class="pln"> b</span><span class="pun">(</span><span class="pln">s</span><span class="pun">),</span><span class="pln"> e</span><span class="pun">(</span><span class="pln">f</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

        array_view</span><span class="pun">(</span><span class="pln">T </span><span class="pun">*</span><span class="pln">s</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> length</span><span class="pun">):</span><span class="pln"> array_view</span><span class="pun">(</span><span class="pln">s</span><span class="pun">,</span><span class="pln"> s </span><span class="pun">+</span><span class="pln"> length</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span></pre>

<p>
	منشئ sfinae، يأخذ أي حاوية تدعم <code>()data.</code> أو مدىً (range) آخَر في خطوة واحدة. …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_41" style="">
<span class="pln">        </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Src</span><span class="pun">,</span><span class="pln">
            std</span><span class="pun">::</span><span class="typ">enable_if_t</span><span class="pun">&lt;</span><span class="pln">compatible_data</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="typ">remove_reference_t</span><span class="pun">&lt;</span><span class="typ">Src</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">&amp;,</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{},</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&gt;*</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">nullptr</span><span class="pun">,</span><span class="pln">
            std</span><span class="pun">::</span><span class="typ">enable_if_t</span><span class="pun">&lt;!</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_same</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="typ">decay_t</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Src</span><span class="pun">&gt;,</span><span class="pln"> array_view</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{},</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&gt;*</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">nullptr</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
            array_view</span><span class="pun">(</span><span class="typ">Src</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> src</span><span class="pun">):</span><span class="pln">
            array_view</span><span class="pun">(</span><span class="pln">src</span><span class="pun">.</span><span class="pln">data</span><span class="pun">(),</span><span class="pln"> src</span><span class="pun">.</span><span class="pln">size</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

        </span><span class="com">// منشئ مصفوفات</span><span class="pln">
        </span><span class="kwd">template</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> N</span><span class="pun">&gt;</span><span class="pln">
            array_view</span><span class="pun">(</span><span class="pln">T</span><span class="pun">(&amp;</span><span class="pln">arr</span><span class="pun">)[</span><span class="pln">N</span><span class="pun">]):</span><span class="pln"> array_view</span><span class="pun">(</span><span class="pln">arr</span><span class="pun">,</span><span class="pln"> N</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

        </span><span class="com">// قائمة مهيئ</span><span class="pln">
        </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> U</span><span class="pun">,</span><span class="pln">
            std</span><span class="pun">::</span><span class="typ">enable_if_t</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_same</span><span class="pun">&lt;</span><span class="kwd">const</span><span class="pln"> U</span><span class="pun">,</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{},</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&gt;*</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">nullptr</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
                array_view</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">initializer_list</span><span class="pun">&lt;</span><span class="pln">U</span><span class="pun">&gt;</span><span class="pln"> il</span><span class="pun">):</span><span class="pln"> array_view</span><span class="pun">(</span><span class="pln">il</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> il</span><span class="pun">.</span><span class="pln">end</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="pun">};</span></pre>

<p>
	تأخذ <code>‎array_view‎</code> أيّ حاوية تدعم تابعَ <code>‎.data()‎</code> يعيد مؤشّرًا إلى النوع <code>‎T‎</code>، وتابعَ <code>‎.size()‎</code> آخر أو مصفوفة، ثم تشطبها لتصبح مجالًا عشوائيّ الوصول (random-access range) إلى عناصر متجاورة من النوع <code>‎T‎</code>.
</p>

<p>
	<code>‎array_view‎</code> يمكن أن تأخذ <code>‎std::vector&lt;T&gt;‎</code> أو <code>‎std::string&lt;T&gt;‎</code> أو <code>‎std::array&lt;T, N&gt;‎</code> أو <code>‎T[37]‎</code> أو قائمة مهيئ (initializer list)، بما في ذلك تلك القوائم المبنية بـ <code>‎{}‎</code>، أو أيّ شيءٍ آخر يدعمها (عبر <code>‎T* x.data()‎</code> و <code>‎size_t x.size()‎</code>).
</p>

<p>
	هنا في هذه الحالة، ستعني البيانات التي نستطيع استخراجها من الشيء الذي نشطبه إضافة إلى الحالة غير المالكة (non-owning state) الخاصة بنا أننا لسنا مضطرين إلى تخصيص ذاكرة أو كتابة دوال مخصّصة تعتمد على النوع.
</p>

<p>
	انظر <a data-ss1617022768="1" href="coliru.stacked-crooked.com/a/c9f8e013a309ca66" rel="">هذا المثال الحيّ</a> للتوضيح.
</p>

<p>
	قد يكون أحد التحسينات الممكنة هو استخدام <code>‎data‎</code> و <code>‎size‎</code> غير أعضاء (non-member) في سياق تمكين البحث القائم على الوسائط (ADL).
</p>

<h3>
	شطب النوع عبر std::any
</h3>

<p>
	يستخدم هذا المثال C++‎ 14 و <code>‎boost::any‎</code>. أمّا في C++‎ 17، فيمكنك استخدام <code>‎std::any‎</code> بدلاً من ذلك.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_43" style="">
<span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> print </span><span class="pun">=</span><span class="pln">
    make_any_method</span><span class="pun">&lt;</span><span class="kwd">void</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ostream</span><span class="pun">&amp;)&gt;([](</span><span class="kwd">auto</span><span class="pun">&amp;&amp;</span><span class="pln"> p</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">ostream</span><span class="pun">&amp;</span><span class="pln"> t</span><span class="pun">){</span><span class="pln"> t </span><span class="pun">&lt;&lt;</span><span class="pln"> p </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln"> </span><span class="pun">});</span><span class="pln">
super_any </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">print</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">7</span><span class="pun">;</span><span class="pln">
</span><span class="pun">(</span><span class="pln">a</span><span class="pun">-&gt;*</span><span class="pln">print</span><span class="pun">)(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">);</span></pre>

<p>
	يعتمد هذا المثال على العمل الذي قام به <a data-ss1617022768="1" href="coliru.stacked-crooked.com/a/2ab8d7e41d24e616" rel="">‎‎@dyp</a> و <a data-ss1617022768="1" href="https://stackoverflow.com/questions/38835747/type-erasing-type-erasure-any-questions/38865269#38865269" rel="external nofollow">‎‎@cpplearner</a>، مع مساهمةٍ من <a data-ss1617022768="1" href="https://stackoverflow.com/users/1774667/yakk-adam-nevraumont" rel="external nofollow">آدم نيفراومونت</a>. سنستخدم أولاً وسمًا لتمرير الأنواع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_45" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">tag_t</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">constexpr</span><span class="pln"> </span><span class="typ">tag_t</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">constexpr</span><span class="pln"> </span><span class="typ">tag_t</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> tag </span><span class="pun">{};</span></pre>

<p>
	يحصل هذا الصنف على البصمة (signature) المُخزّنة باستخدام <code>‎any_method‎</code>، وينشئ هذا نوع مؤشّر دالة (function pointer type)، ومُنتِجًا - factory - لمؤشّرات الدوال المذكورة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_47" style="">
<span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> any_method</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> any_sig_from_method </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> any_method</span><span class="pun">::</span><span class="pln">signature</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> any_method</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Sig</span><span class="pun">=</span><span class="pln">any_sig_from_method</span><span class="str">&lt;any_method&gt;</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> any_method_function</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> any_method</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> R</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="typ">Args</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> any_method_function</span><span class="pun">&lt;</span><span class="pln">any_method</span><span class="pun">,</span><span class="pln"> R</span><span class="pun">(</span><span class="typ">Args</span><span class="pun">...)&gt;</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> decorate </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">conditional_t</span><span class="pun">&lt;</span><span class="pln"> any_method</span><span class="pun">::</span><span class="pln">is_const</span><span class="pun">,</span><span class="pln"> T </span><span class="kwd">const</span><span class="pun">,</span><span class="pln"> T </span><span class="pun">&gt;;</span><span class="pln">

        </span><span class="kwd">using</span><span class="pln"> any </span><span class="pun">=</span><span class="pln"> decorate</span><span class="pun">&lt;</span><span class="pln">boost</span><span class="pun">::</span><span class="pln">any </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">;</span><span class="pln">

       </span><span class="kwd">using</span><span class="pln"> type </span><span class="pun">=</span><span class="pln"> R</span><span class="pun">(*)(</span><span class="pln">any</span><span class="pun">&amp;,</span><span class="pln"> any_method </span><span class="kwd">const</span><span class="pun">*,</span><span class="pln"> </span><span class="typ">Args</span><span class="pun">&amp;&amp;...);</span><span class="pln">
        </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
        type </span><span class="kwd">operator</span><span class="pun">()(</span><span class="typ">tag_t</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> T</span><span class="pun">&gt;)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
           </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">+[](</span><span class="pln">any</span><span class="pun">&amp;</span><span class="pln"> self</span><span class="pun">,</span><span class="pln"> any_method </span><span class="kwd">const</span><span class="pun">*</span><span class="pln"> method</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Args</span><span class="pun">&amp;&amp;...</span><span class="pln">args</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
               </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(*</span><span class="pln">method</span><span class="pun">)(</span><span class="pln"> boost</span><span class="pun">::</span><span class="pln">any_cast</span><span class="pun">&lt;</span><span class="pln">decorate</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;&amp;&gt;(</span><span class="pln">self</span><span class="pun">),</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">args</span><span class="pun">)(</span><span class="pln">args</span><span class="pun">)...</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
            </span><span class="pun">};</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span></pre>

<ul>
<li>
		<code>any_method_function::type</code> - يمثّل نوع مؤشّر الدالّة الذي سنخزّنه بجانب النُسخة.
	</li>
	<li>
		<code>any_method_function::operator()‎</code> - يأخذ <code>tag_t&lt;T&gt;‎</code> ويكتب نُسخةً مخصّصة من النوع <code>any_method_function::type</code>، والتي تفترض أنّ <code>‎any‎</code> سيساوي <code>‎T‎</code>.
	</li>
</ul>
<p>
	نحن نريد أن نشطب نوع عدّة توابع في الوقت نفسه، لذا سنجمعها في صفوف (tuples) ونكتب مغلِّفًا (wrapper) مساعدًا لتثبيت الصفّ في موقع تخزين ساكن (static storage) لكل نوع على حدة، مع الحفاظ على مؤشّر يشير إليها.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_49" style="">
<span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pun">...</span><span class="pln">any_methods</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> any_method_tuple </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">tuple</span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> any_method_function</span><span class="str">&lt;any_methods&gt;</span><span class="pun">::</span><span class="pln">type</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;;</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pun">...</span><span class="pln">any_methods</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    any_method_tuple</span><span class="pun">&lt;</span><span class="pln">any_methods</span><span class="pun">...&gt;</span><span class="pln"> make_vtable</span><span class="pun">(</span><span class="pln"> </span><span class="typ">tag_t</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_tuple</span><span class="pun">(</span><span class="pln">
            any_method_function</span><span class="str">&lt;any_methods&gt;</span><span class="pun">{}(</span><span class="pln">tag</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;)...</span><span class="pln">
    </span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="pln">methods </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> any_methods
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">private</span><span class="pun">:</span><span class="pln"> any_method_tuple </span><span class="pun">&lt;</span><span class="pln"> methods</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">*</span><span class="pln">vtable </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
      </span><span class="kwd">static</span><span class="pln"> any_method_tuple</span><span class="pun">&lt;</span><span class="pln">methods</span><span class="pun">...&gt;</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">*</span><span class="pln"> get_vtable</span><span class="pun">(</span><span class="pln"> </span><span class="typ">tag_t</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
           </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> table </span><span class="pun">=</span><span class="pln"> make_vtable</span><span class="pun">&lt;</span><span class="pln">methods</span><span class="pun">...&gt;(</span><span class="pln">tag</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;);</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">table</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">public</span><span class="pun">:</span><span class="pln"> any_methods</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
        any_methods</span><span class="pun">(</span><span class="typ">tag_t</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> T</span><span class="pun">&gt;):</span><span class="pln"> vtable</span><span class="pun">(</span><span class="pln">get_vtable</span><span class="pun">(</span><span class="pln">tag </span><span class="pun">&lt;</span><span class="pln"> T</span><span class="pun">&gt;))</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

        any_methods</span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">=(</span><span class="pln">any_methods </span><span class="kwd">const</span><span class="pun">&amp;)=</span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
       </span><span class="kwd">void</span><span class="pln"> change_type</span><span class="pun">(</span><span class="pln"> </span><span class="typ">tag_t</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">={}</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> vtable </span><span class="pun">=</span><span class="pln"> get_vtable</span><span class="pun">(</span><span class="pln">tag</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;);</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> any_method</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">auto</span><span class="pln"> get_invoker</span><span class="pun">(</span><span class="typ">tag_t</span><span class="str">&lt;any_method&gt;</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{})</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">get </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> any_method_function</span><span class="str">&lt;any_method&gt;</span><span class="pun">::</span><span class="pln">type </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(*</span><span class="pln">vtable</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span></pre>

<p>
	يمكننا تخصيص هذا للحالات التي يكون فيها الجدول الوهمي vtable صغيرًا، على سبيل المثال إن كان مؤلفًا من عنصر واحد، واستخدام المؤشّرات المباشرة المخزّنة في الصنف في تلك الحالات لتحسين الكفاءة.
</p>

<p>
	سنستخدم <code>‎super_any_t‎</code> لتيسير تصريح <code>‎super_any‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_51" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="pln">methods </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">super_any_t</span><span class="pun">;</span></pre>

<p>
	يبحث هذا في التوابع التي يدعمها <code>super_any</code> لأجل تطبيق قاعدة "فشل التعويض ليس خطأ أو (SFINAE)" وكذلك تحسين رسائل الخطأ:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_53" style="">
<span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> super_any</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> method</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> super_method_applies_helper </span><span class="pun">:</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">false_type </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> M0</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="typ">Methods</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> method</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> super_method_applies_helper</span><span class="pun">&lt;</span><span class="typ">super_any_t</span><span class="pun">&lt;</span><span class="pln">M0</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Methods</span><span class="pun">...&gt;,</span><span class="pln"> method</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">:</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">integral_constant</span><span class="pun">&lt;</span><span class="kwd">bool</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">is_same</span><span class="pun">&lt;</span><span class="pln">M0</span><span class="pun">,</span><span class="pln"> method</span><span class="pun">&gt;{}</span><span class="pln"> </span><span class="pun">||</span><span class="pln">
super_method_applies_helper</span><span class="pun">&lt;</span><span class="typ">super_any_t</span><span class="pun">&lt;</span><span class="typ">Methods</span><span class="pun">...&gt;,</span><span class="pln"> method</span><span class="pun">&gt;{}&gt;</span><span class="pln">
</span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pun">...</span><span class="pln">methods</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> method</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> super_method_test</span><span class="pun">(</span><span class="pln"> </span><span class="typ">super_any_t</span><span class="pun">&lt;</span><span class="pln">methods</span><span class="pun">...&gt;</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">&amp;,</span><span class="pln"> </span><span class="typ">tag_t</span><span class="str">&lt;method&gt;</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">integral_constant</span><span class="pun">&lt;</span><span class="kwd">bool</span><span class="pun">,</span><span class="pln"> super_method_applies_helper</span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">super_any_t</span><span class="pun">&lt;</span><span class="pln">methods</span><span class="pun">...&gt;,</span><span class="pln"> method
</span><span class="pun">&gt;{}</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> method</span><span class="pun">::</span><span class="pln">is_const </span><span class="pun">&gt;{};</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pun">...</span><span class="pln">methods</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> method</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> super_method_test</span><span class="pun">(</span><span class="pln"> </span><span class="typ">super_any_t</span><span class="pun">&lt;</span><span class="pln">methods</span><span class="pun">...&gt;&amp;,</span><span class="pln"> </span><span class="typ">tag_t</span><span class="str">&lt;method&gt;</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">integral_constant</span><span class="pun">&lt;</span><span class="kwd">bool</span><span class="pun">,</span><span class="pln"> super_method_applies_helper</span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">super_any_t</span><span class="pun">&lt;</span><span class="pln">methods</span><span class="pun">...&gt;,</span><span class="pln"> method
</span><span class="pun">&gt;{}</span><span class="pln"> </span><span class="pun">&gt;{};</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> super_any</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> method</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> super_method_applies</span><span class="pun">:</span><span class="pln">
</span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln"> super_method_test</span><span class="pun">(</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">declval</span><span class="str">&lt;super_any&gt;</span><span class="pun">(),</span><span class="pln"> tag</span><span class="str">&lt;method&gt;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="pun">{};</span></pre>

<p>
	بعد ذلك سننشئ النوع <code>‎any_method‎</code>، وهو عبارة عن مؤشّر إلى تابع زائف (pseudo-method-pointer). سنجعله عامًّا (globally) و ثابتًا (<code>‎const‎</code>) باستخدام الصياغة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_55" style="">
<span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> print </span><span class="pun">=</span><span class="pln"> make_any_method</span><span class="pun">([](</span><span class="kwd">auto</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> self</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> os</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    os </span><span class="pun">&lt;&lt;</span><span class="pln"> self</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">});</span></pre>

<p>
	و في C++‎ 17:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_57" style="">
<span class="kwd">const</span><span class="pln"> any_method print </span><span class="pun">=[](</span><span class="kwd">auto</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> self</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> os</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    os </span><span class="pun">&lt;&lt;</span><span class="pln"> self</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	لاحظ أنّ عدم استخدام تعابير لامدا قد يتسبّب في فوضى إذ أنّنا نستخدم النوع في البحث، يمكن إصلاح هذا الخلل، لكنّ ذلك سيجعل هذا المثال أطول ممّا هو عليه. وبشكل عام، يجب أن تهيئ توابع <code>any</code> بواسطة تعبير لامدا، أو صنف ذي معامِلات غير محددة النوع (Parameterised type) في لامدا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_59" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Sig</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> const_method</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> F</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> any_method
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> signature </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Sig</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">enum</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            is_const </span><span class="pun">=</span><span class="pln"> const_method
        </span><span class="pun">};</span><span class="pln">
        </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
            F f</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Any</span><span class="pun">,</span><span class="pln">
            </span><span class="com">// تطابق هذا النوع Anys من أنّ أحد كائنات SFINAE تتحقق قاعدة</span><span class="pln">
            std</span><span class="pun">::</span><span class="typ">enable_if_t</span><span class="pun">&lt;</span><span class="pln">super_method_applies </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Any</span><span class="pln"> </span><span class="pun">&amp;&amp;,</span><span class="pln"> any_method</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{},</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&gt;*</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">nullptr</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
            </span><span class="kwd">friend</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">-&gt;*(</span><span class="pln"> </span><span class="typ">Any</span><span class="pun">&amp;&amp;</span><span class="pln"> self</span><span class="pun">,</span><span class="pln"> any_method </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> m </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span></pre>

<p>
	لا تستخدم قيمة <code>any_method</code> إذ لكل تابع <code>any_method</code> نوعًا خاصًا، وتحقق أن لكل عنصر <code>*auto</code> في <code>super_any</code> مؤشرًا يشير إليك. ثم أرسل إلى <code>any_method_data</code>، تابع …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_61" style="">
<span class="pln">m</span><span class="pun">](</span><span class="kwd">auto</span><span class="pun">&amp;&amp;...</span><span class="pln">args</span><span class="pun">)-&gt;</span><span class="kwd">decltype</span><span class="pun">(</span><span class="kwd">auto</span><span class="pun">)</span><span class="pln">
                </span><span class="pun">{</span><span class="pln">
                    </span><span class="kwd">return</span><span class="pln"> invoke</span><span class="pun">(</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)(</span><span class="pln">self</span><span class="pun">),</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">m</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">args</span><span class="pun">)(</span><span class="pln">args</span><span class="pun">)...</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
                </span><span class="pun">};</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">

        any_method</span><span class="pun">(</span><span class="pln">F fin</span><span class="pun">):</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">fin</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

        </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="typ">Args</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
            </span><span class="kwd">decltype</span><span class="pun">(</span><span class="kwd">auto</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">()(</span><span class="typ">Args</span><span class="pun">&amp;&amp;...</span><span class="pln">args</span><span class="pun">)</span><span class="kwd">const</span><span class="pln"> 
            </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="typ">Args</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">args</span><span class="pun">)...);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span></pre>

<p>
	هذا تابعٌ منتِج (factory method)، لكني لا أراه ضروريًا في C++‎ 17:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_63" style="">
<span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Sig</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> is_const</span><span class="pun">=</span><span class="kwd">false</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> F</span><span class="pun">&gt;</span><span class="pln">
any_method</span><span class="pun">&lt;</span><span class="typ">Sig</span><span class="pun">,</span><span class="pln"> is_const</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">decay_t</span><span class="pun">&lt;</span><span class="pln">F</span><span class="pun">&gt;&gt;</span><span class="pln">
make_any_method</span><span class="pun">(</span><span class="pln"> F</span><span class="pun">&amp;&amp;</span><span class="pln"> f </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="pln">std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="pln">F</span><span class="pun">&gt;(</span><span class="pln">f</span><span class="pun">)};</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هذه هي <code>‎any‎</code> المُعزّزة، فهي من النوع <code>‎any‎</code>، وتحمل معها حزمة من مؤشّرات دوال شطب النوع (type-erasure function pointers) التي تتغيّر كلما تغيّرت <code>‎any‎</code> المحتواة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_65" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="pln">methods </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">super_any_t</span><span class="pun">:</span><span class="pln"> boost</span><span class="pun">::</span><span class="pln">any</span><span class="pun">,</span><span class="pln"> any_methods </span><span class="pun">&lt;</span><span class="pln"> methods</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> vtable </span><span class="pun">=</span><span class="pln"> any_methods </span><span class="pun">&lt;</span><span class="pln"> methods</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">public</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">,</span><span class="pln">
        std</span><span class="pun">::</span><span class="typ">enable_if_t</span><span class="pun">&lt;</span><span class="pln"> </span><span class="pun">!</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_base_of</span><span class="pun">&lt;</span><span class="typ">super_any_t</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">decay_t</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;&gt;{},</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">=</span><span class="lit">0</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
        </span><span class="typ">super_any_t</span><span class="pun">(</span><span class="pln"> T</span><span class="pun">&amp;&amp;</span><span class="pln"> t </span><span class="pun">):</span><span class="pln"> boost</span><span class="pun">::</span><span class="pln">any</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">t</span><span class="pun">))</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">using</span><span class="pln"> dT </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">decay_t</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
            </span><span class="kwd">this</span><span class="pun">-&gt;</span><span class="pln">change_type</span><span class="pun">(</span><span class="pln">tag </span><span class="pun">&lt;</span><span class="pln"> dT</span><span class="pun">&gt;);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        boost</span><span class="pun">::</span><span class="pln">any</span><span class="pun">&amp;</span><span class="pln"> as_any</span><span class="pun">()&amp;{</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">;}</span><span class="pln">
        boost</span><span class="pun">::</span><span class="pln">any</span><span class="pun">&amp;&amp;</span><span class="pln"> as_any</span><span class="pun">()&amp;&amp;{</span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(*</span><span class="kwd">this</span><span class="pun">);}</span><span class="pln">
        boost</span><span class="pun">::</span><span class="pln">any </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> as_any</span><span class="pun">()</span><span class="kwd">const</span><span class="pun">&amp;{</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">;}</span><span class="pln">

        </span><span class="typ">super_any_t</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
        </span><span class="typ">super_any_t</span><span class="pun">(</span><span class="typ">super_any_t</span><span class="pun">&amp;&amp;</span><span class="pln"> o</span><span class="pun">):</span><span class="pln"> boost</span><span class="pun">::</span><span class="pln">any</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">o</span><span class="pun">.</span><span class="pln">as_any</span><span class="pun">())),</span><span class="pln">
        vtable</span><span class="pun">(</span><span class="pln">o</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

        </span><span class="typ">super_any_t</span><span class="pun">(</span><span class="typ">super_any_t</span><span class="pln">
            </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> o</span><span class="pun">):</span><span class="pln"> boost</span><span class="pun">::</span><span class="pln">any</span><span class="pun">(</span><span class="pln">o</span><span class="pun">.</span><span class="pln">as_any</span><span class="pun">()),</span><span class="pln">
        vtable</span><span class="pun">(</span><span class="pln">o</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

        </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> S</span><span class="pun">,</span><span class="pln">
        std</span><span class="pun">::</span><span class="typ">enable_if_t</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_same</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="typ">decay_t</span><span class="pun">&lt;</span><span class="pln">S</span><span class="pun">&gt;,</span><span class="pln"> </span><span class="typ">super_any_t</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{},</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
        </span><span class="typ">super_any_t</span><span class="pun">(</span><span class="pln"> S</span><span class="pun">&amp;&amp;</span><span class="pln"> o </span><span class="pun">):</span><span class="pln"> boost</span><span class="pun">::</span><span class="pln">any</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="pln">S</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">o</span><span class="pun">).</span><span class="pln">as_any</span><span class="pun">()),</span><span class="pln">
        vtable</span><span class="pun">(</span><span class="pln">o</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

        </span><span class="typ">super_any_t</span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">=(</span><span class="typ">super_any_t</span><span class="pun">&amp;&amp;)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
        </span><span class="typ">super_any_t</span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">=(</span><span class="typ">super_any_t</span><span class="pln">
            </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">

        </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">,</span><span class="pln">
       std</span><span class="pun">::</span><span class="typ">enable_if_t</span><span class="pun">&lt;</span><span class="pln"> </span><span class="pun">!</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_same</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="typ">decay_t</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;,</span><span class="pln"> </span><span class="typ">super_any_t</span><span class="pun">&gt;{},</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&gt;*</span><span class="pln"> </span><span class="pun">=</span><span class="kwd">nullptr</span><span class="pln">     </span><span class="pun">&gt;</span><span class="pln">
        </span><span class="typ">super_any_t</span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">=(</span><span class="pln"> T</span><span class="pun">&amp;&amp;</span><span class="pln"> t </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
     </span><span class="pun">((</span><span class="pln">boost</span><span class="pun">::</span><span class="pln">any</span><span class="pun">&amp;)*</span><span class="kwd">this</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;(</span><span class="pln">t</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> dT</span><span class="pun">=</span><span class="pln">std</span><span class="pun">::</span><span class="typ">decay_t</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;;</span><span class="pln">
</span><span class="kwd">this</span><span class="pun">-&gt;</span><span class="pln">change_type</span><span class="pun">(</span><span class="pln"> tag</span><span class="str">&lt;dT&gt;</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	تخزين التوابع <code>‎any_method‎</code> ككائنات ثابتة (<code>‎const‎</code>) يُسهّل <code>‎super_any‎</code> بعض الشيء:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_67" style="">
<span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pun">...</span><span class="typ">Ts</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> super_any </span><span class="pun">=</span><span class="pln"> </span><span class="typ">super_any_t</span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">remove_cv_t</span><span class="pun">&lt;</span><span class="typ">Ts</span><span class="pun">&gt;...</span><span class="pln"> </span><span class="pun">&gt;;</span></pre>

<p>
	شيفرة تختبر ما سبق:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_69" style="">
<span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> print </span><span class="pun">=</span><span class="pln"> make_any_method</span><span class="pun">&lt;</span><span class="kwd">void</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ostream</span><span class="pun">&amp;)&gt;([](</span><span class="kwd">auto</span><span class="pun">&amp;&amp;</span><span class="pln"> p</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">ostream</span><span class="pun">&amp;</span><span class="pln"> t</span><span class="pun">){</span><span class="pln"> t </span><span class="pun">&lt;&lt;</span><span class="pln"> p </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln"> </span><span class="pun">});</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> wprint </span><span class="pun">=</span><span class="pln"> make_any_method</span><span class="pun">&lt;</span><span class="kwd">void</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">wostream</span><span class="pun">&amp;)&gt;([](</span><span class="kwd">auto</span><span class="pun">&amp;&amp;</span><span class="pln"> p</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">wostream</span><span class="pun">&amp;</span><span class="pln"> os </span><span class="pun">){</span><span class="pln"> os </span><span class="pun">&lt;&lt;</span><span class="pln"> p </span><span class="pun">&lt;&lt;</span><span class="pln"> L</span><span class="str">"\n"</span><span class="pun">;</span><span class="pln"> </span><span class="pun">});</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    super_any </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">print</span><span class="pun">),</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">wprint</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">7</span><span class="pun">;</span><span class="pln">
    super_any </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">print</span><span class="pun">),</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">wprint</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> a2 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">7</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">(</span><span class="pln">a</span><span class="pun">-&gt;*</span><span class="pln">print</span><span class="pun">)(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">(</span><span class="pln">a</span><span class="pun">-&gt;*</span><span class="pln">wprint</span><span class="pun">)(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">wcout</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<a data-ss1617022768="1" href="http://coliru.stacked-crooked.com/a/fbd10edb3336cce1" rel="external nofollow">هذا مثال حيّ </a> على ذلك.
</p>

<h2>
	الأنواع الذرية Atomic Types
</h2>

<p>
	يمكن استخدام الأنواع الذرية للقراءة والكتابة بأمان في موضع من الذاكرة مشترك بين خيطين، وهذا ما يسمى الوصول متعدّد الخيوط Multi-threaded Access. انظر المثال التالي على نموذج سيء ويحتمل أن يتسبب في مشكلة سباق بيانات (Data Race)، ستضيف الدالة كل القيم الموجودة بين <code>a</code> و <code>b</code> إلى <code>result</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_71" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;thread&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> add</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">result</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> a</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;=</span><span class="pln"> b</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="pun">*</span><span class="pln">result </span><span class="pun">+=</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">//  نوع بيانات أولي غير مؤمَّن خيطيًا</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> shared </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span></pre>

<p>
	هنا، أنشئ خيطًا يمكنه العمل بشكل موازي للخيط الرئيسي، لينفّذ دالة <code>add</code> المعرَّفة أعلاه بحيث يكون معامِل <code>a</code> يساوي 1، و<code>b</code> يساوي 100، والنتيجة <code>result</code> تساوي <code>shared&amp;</code>. هذا مماثل لـ (;add, 1, 100, &amp;shared) انظر …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_73" style="">
<span class="pln">     std</span><span class="pun">::</span><span class="pln">thread addingThread</span><span class="pun">(</span><span class="pln">add</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">100</span><span class="pun">,</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">shared</span><span class="pun">);</span></pre>

<p>
	حاول طباعة قيمة <code>shared</code> إلى الشاشة، سيكرر الخيط الرئيسي ذلك إلى أن يصبح <code>addingThread</code> قابلًا للضم، انظر…
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_75" style="">
<span class="pln">    </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">addingThread</span><span class="pun">.</span><span class="pln">joinable</span><span class="pun">())</span><span class="pln">
    </span><span class="pun">{</span></pre>

<p>
	قد يتسبب هذا في سلوك غير محدد أو في طباعة قيمة غير صالحة إن حاول <code>addingThread</code> كتابة <code>shared</code> أثناء قراءة الخيط الرئيسي لها، …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_78" style="">
<span class="pln">        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> shared </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// إعادة ضم الخيط عند نهاية التنفيذ لأغراض التنظيف</span><span class="pln">
    addingThread</span><span class="pun">.</span><span class="pln">join</span><span class="pun">();</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	قد يتسبب المثال أعلاه في قراءة خاطئة وقد يؤدّي إلى سلوك غير مُحدّد. انظر المثال التالي على استخدام آمن للخيوط (thread safety)، ستضيف الدالة كل القيم الواقعة بين <code>a</code> و <code>b</code> إلى <code>result</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_80" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;atomic&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;thread&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> add</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">atomic</span><span class="str">&lt;int&gt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln">result</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> a</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;=</span><span class="pln"> b</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// تلقائيا result إلى 'i' إضافة</span><span class="pln">
        result</span><span class="pun">-&gt;</span><span class="pln">fetch_add</span><span class="pun">(</span><span class="pln">i</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// استخدام قالب ذري لتخزين كائنات غير ذرية</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">atomic</span><span class="str">&lt;int&gt;</span><span class="pln"> shared </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span></pre>

<p>
	هنا، أنشئ خيطًا يمكنه العمل بشكل موازي للخيط الرئيسي، لينفّذ دالة <code>add</code> المعرَّفة أعلاه بحيث يكون معامِل <code>a</code> يساوي 1، و<code>b</code> يساوي 100، والنتيجة <code>result</code> تساوي <code>shared&amp;</code>. هذا مماثل لـ (;add, 1, 100, &amp;shared) انظر …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_82" style="">
<span class="pln">    std</span><span class="pun">::</span><span class="pln">thread addingThread</span><span class="pun">(</span><span class="pln">add</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">100</span><span class="pun">,</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">shared</span><span class="pun">);</span></pre>

<p>
	حاول طباعة قيمة <code>shared</code> إلى الشاشة، سيكرر الخيط الرئيسي ذلك إلى أن يصبح <code>addingThread</code> قابلًا للضم، انظر…
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_84" style="">
<span class="pln">    </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">addingThread</span><span class="pun">.</span><span class="pln">joinable</span><span class="pun">())</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// طريقة آمنة لقراءة القيمة المشارَكة من أجل قراءة آمنة خيطيًا.</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> shared</span><span class="pun">.</span><span class="pln">load</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// إعادة ضم الخيط عند نهاية التنفيذ لأغراض التنظيف</span><span class="pln">
    addingThread</span><span class="pun">.</span><span class="pln">join</span><span class="pun">();</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	المثال أعلاه آمن لأنّ جميع عمليات <code>‎store()‎</code> و <code>‎load()‎</code> الخاصّة بالبيانات الذرية (<code>‎atomic‎</code>) تحمي العدد <code>‎int‎</code> المغلّف من محاولات الوصول الآني (simultaneous access).
</p>

<h2>
	تحويلات النوع الصريحة Explicit type conversions
</h2>

<p>
	يمكن تحويل تعبير بشكل صريح إلى نوع <code>‎T‎</code> باستخدام <code>‎dynamic_cast&lt;T&gt;‎</code> أو <code>‎static_cast&lt;T&gt;‎</code> أو <code>‎reinterpret_cast‎</code> <t> أو <code>‎const_cast‎</code> <t>، وذلك اعتمادًا على النوع الذي تريد التحويل إليه. </t></t></p>

<p>
	كذلك تدعم C++‎ صيغة التحويل الدالّية - function-style cast -‏ <code>‎T(expr)‎</code>، وصيغة التحويل على نمط C ‏<code>‎(T)expr‎</code>.
</p>

<h3>
	التحويل على نمط C
</h3>

<p>
	سُمّي كذلك لأنّه التحويل الوحيد الذي يمكن استخدامه في C. وصياغته على الشكل التالي <code>‎(NewType)variable‎</code>. يستخدم هذا التحويل أحد تحويلات C++‎ التالية (بالترتيب):
</p>

<ul>
<li>
		<code>const_cast&lt;NewType&gt;(variable)‎</code>
	</li>
	<li>
		<code>static_cast&lt;NewType&gt;(variable)‎</code>
	</li>
	<li>
		<code>const_cast&lt;NewType&gt;(static_cast&lt;const NewType&gt;(variable))‎</code>
	</li>
	<li>
		<code>reinterpret_cast&lt;const NewType&gt;(variable)‎</code>
	</li>
	<li>
		<code>const_cast&lt;NewType&gt;(reinterpret_cast&lt;const NewType&gt;(variable))‎</code>
	</li>
</ul>
<p>
	صيغة التحويل الدوالي مشابهة جدًا رغم وجود بعض القيود الناتجة عن الصيغة: <code>‎NewType(expression)‎</code>، ونتيجة لذلك لا يمكن التحويل إلّا إلى الأنواع التي لا تحتوي على مسافات فارغة.
</p>

<p>
	يُفضّل استخدام تحويل C++‎ الجديد لأنّه أسهل قراءةً ويمكن رصده بسهولة داخل شيفرة C++‎ المصدرية، كما يمكن رصَد الأخطاء في وقت التصريف وليس في وقت التشغيل. ونظرًا لأنّ هذا التحويل قد ينتج عنه <code>‎reinterpret_cast‎</code> غير مقصود، فإنّه غالبًا ما يُعدُّ خطيرًا.
</p>

<h3>
	التخلّص من الثباتية Casting away constness
</h3>

<p>
	يمكن تحويل مؤشّر-إلى-كائن-ثابت إلى مؤشّر-إلى-كائن-غير-ثابت باستخدام الكلمة المفتاحية <code>‎const_cast‎</code>، وسنستخدمها لاستدعاء دالّة غير صحيحة ثباتيًا (const-correct) ولا تقبل إلّا وسيطا غير ثابت من النوع <code>‎char*‎</code>، رغم أنّها لا تكتُب في المؤشّر أبدًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_86" style="">
<span class="kwd">void</span><span class="pln"> bad_strlen</span><span class="pun">(</span><span class="kwd">char</span><span class="pun">*);</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">*</span><span class="pln">s </span><span class="pun">=</span><span class="pln"> </span><span class="str">"hello, world!"</span><span class="pun">;</span><span class="pln">
bad_strlen</span><span class="pun">(</span><span class="pln">s</span><span class="pun">);</span><span class="pln">    </span><span class="com">// خطأ تصريفي</span><span class="pln">
bad_strlen</span><span class="pun">(</span><span class="kwd">const_cast</span><span class="pun">&lt;</span><span class="kwd">char</span><span class="pun">*&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">s</span><span class="pun">));</span><span class="pln">   </span></pre>

<p>
	في الشيفرة السابقة، يفضل جعل <code>bad_strlen</code> تقبل معامِل <code>*const char</code>. يمكن أن يُستخدم إشارة <code>‎const_cast‎</code> إلى نوع معيّن في تحويل قيمة يسارية مُؤهّلة ثباتيًا (const-qualiﬁed) إلى قيمة يمينية غير مؤهّلة ثباتيًا. لكن يكتنف استخدام<code>‎const_cast‎</code> بعض الخطورة لأنّه يجعل من المستحيل على نظام الأنواع في C++‎ أن يمنعك من محاولة تعديل كائن ثابت. وهو أمر سيؤدّي إلى سلوك غير مُحدّد.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_88" style="">
<span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">123</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pun">&amp;</span><span class="pln"> mutable_x </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">const_cast</span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&amp;&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span><span class="pln">
mutable_x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">456</span><span class="pun">;</span><span class="pln">    </span><span class="com">// قد يُصرَّف، لكنه قد يُنتِجُ سلوكًا غير محدد</span></pre>

<h3>
	التحويل من صنف أساسي إلى صنف مشتق منه
</h3>

<p>
	يمكن تحويل مؤشّر لصنف أساسي إلى مؤشّر لصنف مشتق منه باستخدام <code>‎static_cast‎</code>، ولا تُجري <code>‎static_cast‎</code> أيّ تحقّق في وقت التشغيل، لذلك قد يحدث سلوك غير مُحدّد في حال كان المؤشّر يشير إلى نوعٍ غير النوع المطلوب.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_90" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Derived</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="typ">Derived</span><span class="pln"> d</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Base</span><span class="pun">*</span><span class="pln"> p1 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">d</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Derived</span><span class="pun">*</span><span class="pln"> p2 </span><span class="pun">=</span><span class="pln"> p1</span><span class="pun">;</span><span class="pln">   </span><span class="com">// خطأ، لا بد من التحويل</span><span class="pln">
</span><span class="typ">Derived</span><span class="pun">*</span><span class="pln"> p3 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="typ">Derived</span><span class="pun">*&gt;(</span><span class="pln">p1</span><span class="pun">);</span><span class="pln">  </span><span class="com">// يشير الآن إلى الكائن المشتق p2 لا بأس فـ</span><span class="pln">
</span><span class="typ">Base</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Base</span><span class="pun">*</span><span class="pln"> p4 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">b</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Derived</span><span class="pun">*</span><span class="pln"> p5 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="typ">Derived</span><span class="pun">*&gt;(</span><span class="pln">p4</span><span class="pun">);</span><span class="pln">  </span><span class="com">//  p4 سلوك غير محد، لأن</span><span class="pln">
</span><span class="com">// لا يشير إلى كائن مشتق  </span></pre>

<p>
	وبالمثل، يمكن تحويل مرجع يشير إلى الصنف الأساسي إلى مرجع يشير إلى صنف مشتق باستخدام <code>‎static_cast‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_92" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Derived</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="typ">Derived</span><span class="pln"> d</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Base</span><span class="pun">&amp;</span><span class="pln"> r1 </span><span class="pun">=</span><span class="pln"> d</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Derived</span><span class="pun">&amp;</span><span class="pln"> r2 </span><span class="pun">=</span><span class="pln"> r1</span><span class="pun">;</span><span class="pln">   </span><span class="com">// خطأ، لا بدّ من التحويل</span><span class="pln">
</span><span class="typ">Derived</span><span class="pun">&amp;</span><span class="pln"> r3 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="typ">Derived</span><span class="pun">&amp;&gt;(</span><span class="pln">r1</span><span class="pun">);</span><span class="pln">   </span><span class="com">// يشير الآن إلى الكائن المشتق p3 لا بأس فـ</span></pre>

<p>
	إذا كان النوع المصدري متعدد الأشكال فيمكن استخدام <code>‎dynamic_cast‎</code> للتحويل من الصنف الأساسي إلى صنف مشتقّ منه، إذ أنّها تُجري فحصًا في وقت التشغيل، ويمكن معالجة الفشل هذه المرّة بدلاً من حدوث سلوك غير محدّد. أما إن كان مؤشّرًا، سيُعاد مؤشّر فارغ عند الفشل. وفي حال كان مرجعًا، سيُطرَح استثناء عند فشل <code>‎std::bad_cast‎</code> (أو صنف مشتق من <code>‎std::bad_cast‎</code>).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_94" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Base</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pun">~</span><span class="typ">Base</span><span class="pun">();</span><span class="pln">
</span><span class="pun">};</span><span class="pln">    </span><span class="com">// هي بنية متعدد الأشكالBase </span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Derived</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="typ">Base</span><span class="pun">*</span><span class="pln"> b1 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Derived</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Derived</span><span class="pun">*</span><span class="pln"> d1 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">dynamic_cast</span><span class="pun">&lt;</span><span class="typ">Derived</span><span class="pun">*&gt;(</span><span class="pln">b1</span><span class="pun">);</span><span class="pln">     </span><span class="com">// يشير الآن إلى الكائن المشتق p1 لا بأس فـ</span><span class="pln">
</span><span class="typ">Base</span><span class="pun">*</span><span class="pln"> b2 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Base</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Derived</span><span class="pun">*</span><span class="pln"> d2 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">dynamic_cast</span><span class="pun">&lt;</span><span class="typ">Derived</span><span class="pun">*&gt;(</span><span class="pln">b2</span><span class="pun">);</span><span class="pln">  </span><span class="com">// هو مؤشر فارغ d2</span></pre>

<h3>
	التحويل بين المؤشرات والأعداد الصحيحة
</h3>

<p>
	يمكن تحويل مؤشّر كائن (بما في ذلك <code>‎void*‎</code>) أو مؤشّر دالّة إلى نوع عددي صحيح باستخدام <code>‎reinterpret_cast‎</code>، ولن يُصرَّف هذا إلّا إذا كان النوع المقصود طويلاً بما فيه الكفاية. تتعلّق النتيجة بالتنفيذ، وتعيد في العادةً العنوان العددي للبايت الذي يشير إليه المؤشّر في الذاكرة.
</p>

<p>
	وعمومًا فالنوعين <code>‎long‎</code> و <code>‎unsigned long‎</code> طويلان بما يكفي لحفظ أيّ قيمة للمؤشّر، لكنّ هذا غير مضمون من قبل المعيار.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	في حال وجود النوعين <code>‎std::intptr_t‎</code> و <code>‎std::uintptr_t‎</code> فإننا نضمن أن يكفي طولهما لاحتواء <code>‎void*‎</code> (ومن ثم أيّ مؤشّر إلى نوع كائن)، لكن لا نضمن أن يكفي طولهما لاحتواء مؤشّر دالّة.
</p>

<p>
	وبالمثل، يمكن استخدام <code>‎reinterpret_cast‎</code> لتحويل نوع عددي صحيح إلى نوع مؤشّر. ومرّة أخرى، فالنتيجة تتعلّق بالتنفيذ، غير أنّه يُضمَن ألّا يتم تغيير قيمة المؤشّر عن طريق تقريب (round-trip) نوع عددي صحيح، كما لا يضمن المعيار أنّ القيمة صفر ستُحوّل إلى مؤشّر فارغ.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_96" style="">
<span class="kwd">void</span><span class="pln"> register_callback</span><span class="pun">(</span><span class="kwd">void</span><span class="pln"> </span><span class="pun">(*</span><span class="pln">fp</span><span class="pun">)(</span><span class="kwd">void</span><span class="pun">*),</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">*</span><span class="pln"> arg</span><span class="pun">);</span><span class="pln"> 
  </span><span class="com">// C على الأرجح واجهة برمجة تطبيقات للغة </span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> my_callback</span><span class="pun">(</span><span class="kwd">void</span><span class="pun">*</span><span class="pln"> x</span><span class="pun">)</span><span class="pln"> 
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"the value is: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="kwd">reinterpret_cast</span><span class="str">&lt;long&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span><span class="pln">    </span><span class="com">// ستُصرَّف على الأرجح</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">long</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cin </span><span class="pun">&gt;&gt;</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
register_callback</span><span class="pun">(</span><span class="pln">my_callback</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">reinterpret_cast</span><span class="pun">&lt;</span><span class="kwd">void</span><span class="pun">*&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x</span><span class="pun">));</span><span class="pln">    </span><span class="com">// نأمل عدم فقدان أيّ معلومات</span></pre>

<h3>
	التحويل عبر مُنشئ صريح أو دالة تحويل صريحة
</h3>

<p>
	التحويلات التي تشمل استدعاء مُنشئ صريح أو دالّة تحويل لا يمكن إجراؤها ضمنيًا، لكن نستطيع طلب إجراء التحويل بشكل صريح باستخدام <code>‎static_cast‎</code>، ذلك يشبه التهيئة المباشرة (direct initialization) باستثناء أنّ النتيجة تكون مؤقّتة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_98" style="">
<span class="kwd">class</span><span class="pln"> C
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">unique_ptr</span><span class="str">&lt;int&gt;</span><span class="pln"> p</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">explicit</span><span class="pln"> C</span><span class="pun">(</span><span class="typ">int</span><span class="pun">*</span><span class="pln"> p</span><span class="pun">):</span><span class="pln"> p</span><span class="pun">(</span><span class="pln">p</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">C c</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> g</span><span class="pun">(</span><span class="typ">int</span><span class="pun">*</span><span class="pln"> p</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    f</span><span class="pun">(</span><span class="pln">p</span><span class="pun">);</span><span class="pln">    </span><span class="com">// error: C::C(int*) is explicit</span><span class="pln">
    f</span><span class="pun">(</span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="pln">C</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">p</span><span class="pun">));</span><span class="pln">    </span><span class="com">// ok</span><span class="pln">
    f</span><span class="pun">(</span><span class="pln">C</span><span class="pun">(</span><span class="pln">p</span><span class="pun">));</span><span class="pln">    </span><span class="com">// يكافئ السطر الماضي</span><span class="pln">
    C c</span><span class="pun">(</span><span class="pln">p</span><span class="pun">);</span><span class="pln">
    f</span><span class="pun">(</span><span class="pln">c</span><span class="pun">);</span><span class="pln">    </span><span class="com">// error: C is not copyable</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	التحويل الضمني Implicit conversion
</h3>

<p>
	تستطيع أن تُجري <code>‎static_cast‎</code> أيّ تحويل ضمني، وقد يكون هذا مفيدًا أحيانًا كما في الأمثلة التالية:
</p>

<ul>
<li>
		عند تمرير الوسائط إلى علامة حذف (ellipsis)، لن يكون نوع الوسيط "المُتوقَّع" معروفًا بشكل ساكن (statically known)، لذا لن يحدث أي تحويل ضمني.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_100" style="">
<span class="kwd">const</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3.14</span><span class="pun">;</span><span class="pln">
printf</span><span class="pun">(</span><span class="str">"%d\n"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="str">&lt;int&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x</span><span class="pun">));</span><span class="pln">    </span><span class="com">// 3</span><span class="pln">
</span><span class="com">// printf("%d\n", x);    // تتوقع عددا صحيحا هنا printf سلوك غير محد، لأنّ</span><span class="pln">
</span><span class="com">//  حل بديل </span><span class="pln">
</span><span class="com">// const int y = x; printf("%d\n", y);</span></pre>

<p>
	بدون التحويل الصريح للنوع، سيُمرَّر كائن من النوع <code>‎double‎</code> إلى علامة الحذف وسيحدث سلوك غير مُحدّد.
</p>

<ul>
<li>
		يمكن لمُعامل الإسناد الخاصّ بصنف مشتقّ أن يستدعي مُعامل الإسناد الخاصّ بصنفه الأساسي على النحو التالي:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_102" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Base</span><span class="pln">
</span><span class="pun">{</span><span class="pln"> </span><span class="com">/*... */</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Derived</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Base</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Derived</span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">=(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Derived</span><span class="pun">&amp;</span><span class="pln"> other</span><span class="pun">)</span><span class="pln"> 
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="typ">Base</span><span class="pun">&amp;&gt;(*</span><span class="kwd">this</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> other</span><span class="pun">;</span><span class="pln">
        </span><span class="com">// :حل بديل</span><span class="pln">
        </span><span class="com">// Base&amp; this_base_ref = *this; this_base_ref = other;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<h3>
	تحويل التعدادات Enum conversions
</h3>

<p>
	يمكن أن تجري <code>‎static_cast‎</code> عمليّة تحويل من نوع عددي صحيح أو عشري إلى نوع تعدادي (سواء كان نطاقًيا - scoped - أو غير نطاقي - unscoped) والعكس صحيح، كما أنّها تحوّل بين أنواع التعدادات.
</p>

<p>
	*التحويل من نوع تعداد غير نطاقي إلى نوع حسابي (arithmetic type) يُعدُّ تحويلًا ضمنيًا؛ وهو جائز لكنه غير ضروري لاستخدام <code>‎static_cast‎</code>.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<ul>
<li>
		عند تحويل نوع تعداد نطاقي إلى نوع حسابي:
	</li>
	<li>
		إذا كان من الممكن تمثيل قيمة التعداد في النّوع المقصود بشكل تامّ، فإنّ النتيجة ستساوي تلك القيمة.
	</li>
	<li>
		وإلا، ستكون النتيجة غير مُحدّدة إن كان النوع المقصود نوعًا صحيحًا.
	</li>
	<li>
		بخلاف ذلك، إذا كان النوع المقصود نوعًا عشريا (floating point type)، فإنّ النتيجة ستساوي نتيجة التحويل إلى النوع الأساسي، ثم منه إلى نوع الأعداد العشرية. انظر:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_104" style="">
<span class="kwd">enum</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Format</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    TEXT </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln">
        PDF </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">,</span><span class="pln">
        OTHER </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2000</span><span class="pun">,</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">Format</span><span class="pln"> f </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Format</span><span class="pun">::</span><span class="pln">PDF</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> f</span><span class="pun">;</span><span class="pln">    </span><span class="com">// error</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="str">&lt;int&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">f</span><span class="pun">);</span><span class="pln">    </span><span class="com">// يساوي 1000 b </span><span class="pln">
</span><span class="kwd">char</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="str">&lt;char&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">f</span><span class="pun">);</span><span class="pln">    </span><span class="com">//  char غير محدد في حال لم يتناسب 1000 مع النوع</span><span class="pln">
</span><span class="kwd">double</span><span class="pln"> d </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="str">&lt;double&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">f</span><span class="pun">);</span><span class="pln">    </span><span class="com">// يساوي على الأرجح 1000.0 d  </span></pre>

<ul>
<li>
		عند تحويل عدد صحيح أو نوع تعداد إلى نوع تعداد:
	</li>
	<li>
		إذا كانت القيمة الأصلية ضمن مجال (range) التعداد المقصود، فإنّ النتيجة ستساوي تلك القيمة. لاحظ أنّ هذه القيمة قد تختلف من عدّاد (enumerator) لآخر.
	</li>
	<li>
		وإلا، فإنّ النتيجة ستكون غير محددة (unspeciﬁed) في ‏(C++‎ 14&lt;=)، أو غير معرَّفة (undeﬁned) في ‏(C++‎ 17&gt;=). انظر المثال التالي:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_106" style="">
<span class="kwd">enum</span><span class="pln"> </span><span class="typ">Scale</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    SINGLE </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln">
        DOUBLE </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln">
        QUAD </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">Scale</span><span class="pln"> s1 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">    </span><span class="com">// خطأ</span><span class="pln">
</span><span class="typ">Scale</span><span class="pln"> s2 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="typ">Scale</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="lit">2</span><span class="pun">);</span><span class="pln">    </span><span class="com">// DOUBLE من النوع s2 </span><span class="pln">
</span><span class="typ">Scale</span><span class="pln"> s3 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="typ">Scale</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="lit">3</span><span class="pun">);</span><span class="pln">    </span><span class="com">// تساوي 3، وهي غير مساوية لأيّ عدّاد s3 قيمة</span><span class="pln">
</span><span class="typ">Scale</span><span class="pln"> s9 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="typ">Scale</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="lit">9</span><span class="pun">);</span><span class="pln">    </span><span class="com">// C++17 سلوك غير محدد في</span><span class="pln">
</span><span class="com">//  C++14 وقيمة غير موصوفة في</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<ul>
<li>
		عند تحويل نوع عشري إلى نوع تعداد، فإنّ النتيجة ستكون مساوية لنتيجة التحويل إلى النوع الأساسي للتعداد ثمّ إلى نوع التعداد.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_108" style="">
<span class="kwd">enum</span><span class="pln"> </span><span class="typ">Direction</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    UP </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln">
        LEFT </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln">
        DOWN </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln">
        RIGHT </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">Direction</span><span class="pln"> d </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="typ">Direction</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="lit">3.14</span><span class="pun">);</span><span class="pln">   </span></pre>

<h3>
	تحويل المؤشّرات العضوية
</h3>

<p>
	يمكن تحويل مؤشّر يشير إلى عضو من صنف مشتق، إلى مؤشّر يشير إلى عضو من صنفه الأساسي، باستخدام <code>‎static_cast‎</code>، لكن يجب أن تتطابق الأنواع المشار إليها. وإذا كان العامل مؤشّرًا عضويًا فارغًا فإنّ النتيجة ستكون أيضًا مؤشّرًا عضويًا فارغًا.
</p>

<p>
	ولن يكون التحويل صالحًا خلاف ذلك، إلّا إذا كان العضو المُشار إليه عبر المعامَل موجودًا بالفعل في الصنف المقصود، أو كان الصنف المقصود صنفًا أساسيًا أو مشتقًّا من الصنف الذي يحتوي على العضو الذي يشير إليه المعامَل، إذ لا تتحقّق <code>‎static_cast‎</code> من الصحّة (validity). ولن يكون السلوك الناتج محددًا إن لم يكن التحويلُ صالحًا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_110" style="">
<span class="kwd">struct</span><span class="pln"> A </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> B
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> C</span><span class="pun">:</span><span class="pln"> A</span><span class="pun">,</span><span class="pln"> B
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> y</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">double</span><span class="pln"> z</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> B</span><span class="pun">::*</span><span class="pln">p1 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">B</span><span class="pun">::</span><span class="pln">x</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> C</span><span class="pun">::*</span><span class="pln">p2 </span><span class="pun">=</span><span class="pln"> p1</span><span class="pun">;</span><span class="pln">    </span><span class="com">// حسنا، تحويل ضمني</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> B</span><span class="pun">::*</span><span class="pln">p3 </span><span class="pun">=</span><span class="pln"> p2</span><span class="pun">;</span><span class="pln">    </span><span class="com">// خطأ</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> B</span><span class="pun">::*</span><span class="pln">p4 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pln"> B</span><span class="pun">::*&gt;(</span><span class="pln">p2</span><span class="pun">);</span><span class="pln">   </span><span class="com">// p1 يساوي p4  حسنا</span></pre>

<p>
	ما يلي غير معرَّف، إذ يشير <code>p2</code> إلى <code>x</code> وهو عضو من الصنف <code>B</code> وهو غير ذي صلة هنا، نتابع ….
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_112" style="">
<span class="typ">int</span><span class="pln"> A</span><span class="pun">::*</span><span class="pln">p5 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pln"> A</span><span class="pun">::*&gt;(</span><span class="pln">p2</span><span class="pun">);</span><span class="pln">          
</span><span class="kwd">double</span><span class="pln"> C</span><span class="pun">::*</span><span class="pln">p6 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">C</span><span class="pun">::</span><span class="pln">z</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">double</span><span class="pln"> A</span><span class="pun">::*</span><span class="pln">p7 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="kwd">double</span><span class="pln"> A</span><span class="pun">::*&gt;(</span><span class="pln">p6</span><span class="pun">);</span><span class="pln">    </span><span class="com">// z لا تحتوي A لا بأس، رغم أنّ</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> A</span><span class="pun">::*</span><span class="pln">p8 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pln"> A</span><span class="pun">::*&gt;(</span><span class="pln">p6</span><span class="pun">);</span><span class="pln">   </span><span class="com">// error: types don't match</span></pre>

<h3>
	التحويل من *void‎‎ إلى *T‎‎
</h3>

<p>
	في C++‎، لا يمكن تحويل <code>‎void*‎</code> ضمنيًا إلى <code>‎T*‎</code> إن كان <code>‎T‎</code> يمثّل نوعَ كائن، بل يجب استخدام <code>‎static_cast‎</code> لإجراء التحويل بشكل صريح. وإذا كان العامل يشير فعليًا إلى كائن <code>‎T‎</code>، فإنّ النتيجة ستشير إلى ذلك الكائن، وإلا فإنّ النتيجة ستكون غير مُحدّدة.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	وحتى لو لم يكن العامل يشير إلى كائن <code>‎T‎</code>، فما دام المعامَل يشير إلى بايت تمت محاذاة عنوانه بشكل صحيح مع النوع <code>‎T‎</code>، فإنّ نتيجة التحويل ستشير إلى نفس البايت.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_114" style="">
<span class="com">// تخصيص مصفوفة من 100 عدد صحيح بالطريقة الصعبة.</span><span class="pln">
</span><span class="typ">int</span><span class="pun">*</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> malloc</span><span class="pun">(</span><span class="lit">100</span><span class="pun">*</span><span class="kwd">sizeof</span><span class="pun">(*</span><span class="pln">a</span><span class="pun">));</span><span class="pln"> </span><span class="com">// error; malloc returns void*</span><span class="pln">
</span><span class="typ">int</span><span class="pun">*</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">*&gt;(</span><span class="pln">malloc</span><span class="pun">(</span><span class="lit">100</span><span class="pun">*</span><span class="kwd">sizeof</span><span class="pun">(*</span><span class="pln">a</span><span class="pun">)));</span><span class="pln">    </span><span class="com">// حسنا</span><span class="pln">
</span><span class="com">// int* a = new int[100];                            // لا حاجة للتحويل</span><span class="pln">
</span><span class="com">// std::vector&lt;int&gt; a(100);                            // هذا أفضل</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> </span><span class="str">'!'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">*</span><span class="pln"> p1 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">c</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> p2 </span><span class="pun">=</span><span class="pln"> p1</span><span class="pun">;</span><span class="pln">    </span><span class="com">// خطأ</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> p3 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">*&gt;(</span><span class="pln">p1</span><span class="pun">);</span><span class="pln">   </span><span class="com">// c يشير إلى p3 حسنا</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pun">*</span><span class="pln"> p4 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pun">*&gt;(</span><span class="pln">p1</span><span class="pun">);</span><span class="pln"> </span></pre>

<p>
	السطر السابق غير معرَّف في C++03، وقد يكون غير معرَّف في C++11 أيضًا إن كان <code>(alignof(int</code> أكبر من <code>(alignof(int</code>، بقية المثال …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_116" style="">
<span class="kwd">char</span><span class="pun">*</span><span class="pln"> p5 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="kwd">char</span><span class="pun">*&gt;(</span><span class="pln">p1</span><span class="pun">);</span><span class="pln">    </span><span class="com">// error: casting away constness</span></pre>

<h3>
	تحويل مواراة النوع Type punning conversion
</h3>

<p>
	يمكن تحويل مؤشّر (مرجع) يشير إلى نوع كائن، إلى مؤشّر (مرجع) يشير إلى أيّ نوع كائن آخر باستخدام <code>‎reinterpret_cast‎</code> دون الحاجة إلى أيّ منشِئات أو دوالّ تحويل.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_118" style="">
<span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> p </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="kwd">char</span><span class="pun">*&gt;(&amp;</span><span class="pln">x</span><span class="pun">);</span><span class="pln"> </span><span class="com">// error: static_cast cannot perform this conversion</span><span class="pln">
</span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> p </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">reinterpret_cast</span><span class="pun">&lt;</span><span class="kwd">char</span><span class="pun">*&gt;(&amp;</span><span class="pln">x</span><span class="pun">);</span><span class="pln"> </span><span class="com">// حسنا</span><span class="pln">
 </span><span class="pun">*</span><span class="pln">p </span><span class="pun">=</span><span class="pln"> </span><span class="str">'z'</span><span class="pun">;</span><span class="pln">    </span><span class="com">// x ربما يغيّر هذا</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	تمثّل نتيجة <code>‎reinterpret_cast‎</code> نفس العنوان الذي يمثّله العامل، شرط أن تتناسب محاذاة العنوان مع النوع المقصود، وتكون النتيجة غير مُحدّدة في خلاف ذلك.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_120" style="">
<span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">char</span><span class="pun">&amp;</span><span class="pln"> r </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">reinterpret_cast</span><span class="pun">&lt;</span><span class="kwd">char</span><span class="pun">&amp;&gt;(</span><span class="pln">x</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">*</span><span class="pln"> px </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">x</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">*</span><span class="pln"> pr </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">r</span><span class="pun">;</span><span class="pln">
assert</span><span class="pun">(</span><span class="pln">px </span><span class="pun">==</span><span class="pln"> pr</span><span class="pun">);</span></pre>

<p>
	<strong>الإصدار &lt; C++‎ 11</strong>
</p>

<p>
	نتيجة <code>‎reinterpret_cast‎</code> غير مُحدّدة، إلّا أنّ المؤشّر (المرجع) سيتجاوز التقريب (round trip) من نوع المصدر إلى نوع الوجهة، والعكس صحيح طالما أن متطلّبات محاذاة النوع المقصود ليست أكثر صرامة من نظيرتها في نوع المصدر.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_122" style="">
<span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">123</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">unsigned</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&amp;</span><span class="pln"> r1 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">reinterpret_cast</span><span class="pun">&lt;</span><span class="kwd">unsigned</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&amp;&gt;(</span><span class="pln">x</span><span class="pun">);</span><span class="pln">
</span><span class="typ">int</span><span class="pun">&amp;</span><span class="pln"> r2 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">reinterpret_cast</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">&amp;&gt;(</span><span class="pln">r1</span><span class="pun">);</span><span class="pln">
r2 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">456</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 456 إلى x تعيين</span></pre>

<p>
	لا تغيّر <code>‎reinterpret_cast‎</code> العنوانَ في معظم التنفيذات، وهو أمر لم يُعتمد معيارًا حتى الإصدار C++‎ 11.
</p>

<p>
	كذلك يمكن استخدام <code>‎reinterpret_cast‎</code> للتحويل من نوع مؤشّر بيانات عضوية (pointer-to-data-member type) إلى آخر، أو من نوع مؤشر إلى دالة تابعة (pointer- to-member-function type) إلى آخر.
</p>

<p>
	يكتنف استخدام <code>‎reinterpret_cast‎</code> بعض الخطورة، لأنّ القراءة أو الكتابة عبر مؤشّر أو مرجع تم الحصول عليه باستخدام <code>‎reinterpret_cast‎</code> قد يؤدّي إلى حدوث سلوك غير مُحدّد في حال كان نوعي المصدر والوجهة غير مترابطين.
</p>

<h2>
	الأنواع غير المسماة Unnamed types
</h2>

<h3>
	الأصناف غير المسماة Unnamed classes
</h3>

<p>
	على عكس الأصناف أو البنيات المُسمّاة، فإن الأصناف والبنيات غير المُسمّاة يجب استنساخها في موضع تعريفها، ولا يمكن أن يكون لها مُنشئات أو مدمّرات.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_124" style="">
<span class="kwd">struct</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> foo</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">double</span><span class="pln"> bar</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

foobar</span><span class="pun">;</span><span class="pln">
foobar</span><span class="pun">.</span><span class="pln">foo </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">
foobar</span><span class="pun">.</span><span class="pln">bar </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4.0</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">class</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> baz</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> buzz</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">void</span><span class="pln"> setBaz</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> v</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        baz </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

barbar</span><span class="pun">;</span><span class="pln">
barbar</span><span class="pun">.</span><span class="pln">setBaz</span><span class="pun">(</span><span class="lit">15</span><span class="pun">);</span><span class="pln">
barbar</span><span class="pun">.</span><span class="pln">buzz </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span></pre>

<h3>
	استخدام أنواع الأصناف ككُنى للنوع (type aliases)
</h3>

<p>
	يمكن أيضًا استخدام أنواع الأصناف غير المسماة عند إنشاء كُنى (alias) للنوع عبر <code>‎typedef‎</code> و <code>‎using‎</code>:
</p>

<p>
	<strong>الإصدار &lt; C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_126" style="">
<span class="kwd">using</span><span class="pln"> vec2d </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">struct</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">float</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">float</span><span class="pln"> y</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">typedef</span><span class="pln"> </span><span class="kwd">struct</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">float</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">float</span><span class="pln"> y</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

vec2d</span><span class="pun">;</span><span class="pln">
vec2d pt</span><span class="pun">;</span><span class="pln">
pt</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4.</span><span class="pln"> f</span><span class="pun">;</span><span class="pln">
pt</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3.</span><span class="pln"> f</span><span class="pun">;</span></pre>

<h3>
	الأعضاء المجاهيل Anonymous members
</h3>

<p>
	تسمح المصرّفات الشهيرة باستخدام الأصناف كأعضاء مجهولين، لكن هذا غير قياسي في لغة C++‎.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_128" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Example</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> inner_b</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">

    </span><span class="typ">int</span><span class="pln"> outer_b</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// يمكن الوصول إلى أعضاء الهيكل المجهولة كما لو كانت أعضاءً من الهيكل الأب </span><span class="pln">
    </span><span class="typ">Example</span><span class="pun">():</span><span class="pln"> inner_b</span><span class="pun">(</span><span class="lit">2</span><span class="pun">),</span><span class="pln"> outer_b</span><span class="pun">(</span><span class="lit">4</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        inner_b </span><span class="pun">=</span><span class="pln"> outer_b </span><span class="pun">+</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">Example</span><span class="pln"> ex</span><span class="pun">;</span><span class="pln">
</span><span class="com">// نفس الشيء بالنسبة للشيفرات الخارجية التي تشير إلى البنية</span><span class="pln">
ex</span><span class="pun">.</span><span class="pln">inner_b </span><span class="pun">-=</span><span class="pln"> ex</span><span class="pun">.</span><span class="pln">outer_b</span><span class="pun">;</span></pre>

<h3>
	الاتحادات المجهولة Anonymous Unions
</h3>

<p>
	تنتمي أسماء الأعضاء الخاصة باتحاد مجهول (anonymous union) إلى نطاق تصريح الاتّحاد، ويجب أن تكون مميّزة عن جميع الأسماء الأخرى الموجودة في ذلك النطاق. يستخدم المثال التالي نفس الإنشاء (Construction) الذي استخدمناه في مثال الأعضاء المجهولين أعلاه، ولكنّه هذه المرة متوافق مع المعايير.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_130" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Sample</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">union</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> c</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Sample</span><span class="pln"> sa</span><span class="pun">;</span><span class="pln">
    sa</span><span class="pun">.</span><span class="pln">a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln">
    sa</span><span class="pun">.</span><span class="pln">b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4</span><span class="pun">;</span><span class="pln">
    sa</span><span class="pun">.</span><span class="pln">c </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	سمات النوع Type Traits
</h2>

<h3>
	خاصيات النوع Type Properties
</h3>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	تقارن خاصيات النوع المُعدِّلات (modiﬁers) التي يمكن تطبيقها على عدة متغيّرات، لكنّ فائدة تلك السمات لا تكون واضحة في كل حالة. لاحظ أن التحسين الذي يوفّره المثال التالي لن يكون له أثر إلّا إن لم يكن المُصرّف مُحسّنا من الأساس، فهو مجرّد مثال توضيحي.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_132" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">inline</span><span class="pln"> T </span><span class="typ">FastDivideByFour</span><span class="pun">(</span><span class="pln">cont T </span><span class="pun">&amp;</span><span class="pln">var</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// unsigned integral سيحدث خطأ في حال لم يكن النوع المُدخَل نوع عدديا صحيحا غير مؤشّر  </span><span class="pln">
       </span><span class="kwd">static_assert</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_unsigned</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;::</span><span class="pln">value </span><span class="pun">&amp;&amp;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">is_integral</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;::</span><span class="pln">value</span><span class="pun">,</span><span class="pln">
            </span><span class="str">"This function is only designed for unsigned integral types."</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var </span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">2</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span></pre>

<h4>
	is_const
</h4>

<p>
	ستُعاد القيمة <code>true</code> إن كان النوع ثابتًا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_134" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">is_const</span><span class="pun">&lt;</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// true</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_const</span><span class="str">&lt;int&gt;</span><span class="pun">::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// false</span></pre>

<h4>
	is_volatile
</h4>

<p>
	ستُعاد القيمة <code>true</code> إن كان النوع متغيّرًا (volatile).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_136" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_volatile </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">volatile</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&gt;::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// true.</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">is_const</span><span class="pun">&lt;</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// false.</span></pre>

<h4>
	is_signed
</h4>

<p>
	ستُعاد القيمة <code>true</code> إن كان النوع مؤشَّرًا (signed).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_138" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_signed</span><span class="str">&lt;int&gt;</span><span class="pun">::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// true.</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_signed</span><span class="str">&lt;float&gt;</span><span class="pun">::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// true.</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_signed </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">unsigned</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&gt;::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// false.</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_signed</span><span class="str">&lt;uint8_t&gt;</span><span class="pun">::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// false.</span></pre>

<h4>
	is_unsigned
</h4>

<p>
	ستُعاد القيمة <code>true</code> إن كان النوع غير مؤشّر.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_140" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_unsigned </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">unsigned</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&gt;::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// true</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_signed</span><span class="str">&lt;uint8_t&gt;</span><span class="pun">::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// true</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_unsigned</span><span class="str">&lt;int&gt;</span><span class="pun">::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// false </span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_signed</span><span class="str">&lt;float&gt;</span><span class="pun">::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// false</span></pre>

<h3>
	أنواع السمات القياسية Standard type traits
</h3>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	تحتوي الترويسة <code>‎type_traits‎</code> على مجموعة من أصناف القوالب والمساعِدات التي يمكن استخدامها لتحويل خاصيات الأنواع وتفحّصها في وقت التصريف، وتُستخدم هذه السمات عادةً في القوالب للتحقّق من أخطاء المستخدم، ودعم البرمجة العامة، والسماح بتحسينات الأداء. كذلك تُستخدم معظم أنواع السمات للتأكّد ممّا إذا كان النوع يحقّق بعض المعايير. وتُصاغ على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_142" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">struct</span><span class="pln"> is_foo</span><span class="pun">;</span></pre>

<p>
	عند استنساخ صنف من القالب بواسطة نوع يحقّق معيارًا <code>‎foo‎</code>، فإنّ <code>‎is_foo&lt;T&gt;‎</code> سيرث من <code>‎std::integral_constant&lt;bool,true&gt;‎</code> (يُعرَف أيضًا باسم <code>std::true_type</code>)، وإن كان غير ذلك فإنّه يرث من <code>std::integral_constant&lt;bool,false&gt;‎</code> ( ويعرف أيضًا باسم <code>std::false_type</code>). هذا سيمنح للسمة الأعضاء التالية:
</p>

<h4>
	الثوابت
</h4>

<p>
	<code>static constexpr bool value</code>
</p>

<p>
	تعيد <code>true</code> إن كان <code>T</code> يحقّق المعيار <code>foo</code>، وتعيد <code>‎false‎</code> خلاف ذلك.
</p>

<h4>
	الدوال
</h4>

<p>
	<code>operator bool</code>
</p>

<p>
	تعيد <code>‎value‎</code>
</p>

<p>
	<strong>الإصدار ≥ C++‎ 14</strong>
</p>

<p>
	<code>bool operator()‎</code>
</p>

<p>
	تعيد <code>‎value‎</code>
</p>

<h4>
	الأنواع
</h4>

<table>
<thead><tr>
<th>
				الاسم
			</th>
			<th>
				التعريف
			</th>
		</tr></thead>
<tbody><tr>
<td>
				<code>value_type bool type</code>
			</td>
			<td>
				<code>std::integral_constant&lt;bool,value&gt;‎</code>
			</td>
		</tr></tbody>
</table>
<style type="text/css">
table {
    width: 100%;
}

thead {
    vertical-align: middle;
    text-align: center;
}

td, th {
    border: 1px solid #dddddd;
    text-align: right;
    padding: 8px;
    text-align: inherit;

}
tr:nth-child(even) {
    background-color: #dddddd;
}</style>
<p>
	يمكن استخدام السمة في بنيات مثل <code>‎static_assert‎</code> أو <code>‎std::enable_if‎</code>. المثال التالي يستخدم <code>std::is_pointer</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_144" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> i_require_a_pointer</span><span class="pun">(</span><span class="pln">T t</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">static_assert</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_pointer</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;::</span><span class="pln">value</span><span class="pun">,</span><span class="pln"> </span><span class="str">"T must be a pointer type"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="com">// نوعًا مؤشّرًا T التحميل الزائد في حال لم يكن</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">typename</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">enable_if</span><span class="pun">&lt;!</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_pointer</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;::</span><span class="pln">value</span><span class="pun">&gt;::</span><span class="pln">type
does_something_special_with_pointer</span><span class="pun">(</span><span class="pln">T t</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// افعل شيئا عاديا</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// نوعًا مؤشّرًا T التحميل الزائد في حال لم يكن</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">typename</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">enable_if</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_pointer</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;::</span><span class="pln">value</span><span class="pun">&gt;::</span><span class="pln">type
does_something_special_with_pointer</span><span class="pun">(</span><span class="pln">T t</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// افعل شيئا خاصا</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هناك المزيد من السمات التي تُحوّل الأنواع، مثل <code>‎std::add_pointer‎</code> و <code>‎std::underlying_type‎</code>، وتعرض هذه السمات عمومًا نوع عضو يُسمَّى <code>‎type‎</code> يحتوي النوعَ المُحوَّل، كما في <code>std::add_pointer&lt;int&gt;::type is int*‎</code>.
</p>

<h3>
	std::is_same<t t="">‎‎</t>
</h3>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	تُستخدم دالة العلاقة بين الأنواع - type relation‏ - <code>‎std::is_same&lt;T, T&gt;‎</code> لمقارنة نوعين، إذ تعيد <code>true</code> إذا كان النوعان متساويين، و تعيد <code>false</code> خلاف ذلك. في المثال التالي، سيطبع السطر الأول <code>true</code> في أغلب مصرِّفات x86 و x86_64، بينما يطبع السطران الثاني والثالث <code>false</code> في جميع المصرفات.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_146" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_same</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int32_t</span><span class="pun">&gt;::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_same</span><span class="pun">&lt;</span><span class="typ">float</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&gt;::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_same </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">unsigned</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&gt;::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span></pre>

<p>
	تعمل علاقة الأنواع <code>‎std::is_same‎</code> بغض النظر عن التعريفات النوعية typedefs، وهو مُبيَّن في المثال الأوّل عند مقارنة <code>‎int == int32_t‎</code>، لكن ربما لا يكون هذا واضحًا كفاية. انظر المثال التالي إذ سيطبع <code>true</code> في كل المصرفات:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_148" style="">
<span class="kwd">typedef</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">MyType</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_same</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">MyType</span><span class="pun">&gt;::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span></pre>

<h4>
	استخدام std::is_same لإطلاق تحذير عند استخدام صنف أو دالة قالب بطريقة غير صحيحة
</h4>

<p>
	يمكن استخدام <code>‎std::is_same‎</code> مع <code>static_assert</code> لفرض الاستخدام السليم للأصناف والدوال المُقوْلبة. على سبيل المثال، هذه دالّة لا تسمح إلّا بالمُدخلات من النوع <code>‎int‎</code>، والاختيار بين بنيتين.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_150" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;type_traits&gt;</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> foo
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> member</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// متغيّرات أخرى</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> bar
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">char</span><span class="pln"> member</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> </span><span class="typ">AddStructMember</span><span class="pun">(</span><span class="pln">T var1</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> var2</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span></pre>

<p>
	إن كان <code>T != foo || T != bar</code>، اعرض رسالة خطأ، …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_152" style="">
<span class="pln">        </span><span class="kwd">static_assert</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_same</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> foo</span><span class="pun">&gt;::</span><span class="pln">value </span><span class="pun">||</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">is_same</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> bar</span><span class="pun">&gt;::</span><span class="pln">value</span><span class="pun">,</span><span class="pln">
            </span><span class="str">"This function does not support the specified type."</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> var1</span><span class="pun">.</span><span class="pln">member </span><span class="pun">+</span><span class="pln"> var2</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span></pre>

<h3>
	سمات النوع الأساسية
</h3>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	لدينا في ++C عدة أنواع من السمات تقارن بعض الأنواع العامّة كما سنشرح أدناه:
</p>

<h4>
	is_integral
</h4>

<p>
	تعيد القيمة <code>true</code> بالنسبة لجميع أنواع الأعداد الصحيحة، مثل <code>‎int‎</code> و <code>‎char‎</code> و <code>‎long‎</code> و <code>‎unsigned int‎</code> وغيرها.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_154" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_integral</span><span class="str">&lt;int&gt;</span><span class="pun">::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// true.</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_integral</span><span class="str">&lt;char&gt;</span><span class="pun">::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// true.</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_integral</span><span class="str">&lt;float&gt;</span><span class="pun">::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// false.</span></pre>

<h4>
	is_floating_point
</h4>

<p>
	تعيد القيمة <code>true</code> بالنسبة لجميع أنواع الأعداد العشرية، مثل <code>‎float‎</code> و <code>‎double‎</code> و <code>‎long double‎</code> وغيرها
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_156" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_floating_point</span><span class="str">&lt;float&gt;</span><span class="pun">::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// true.</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_floating_point</span><span class="str">&lt;double&gt;</span><span class="pun">::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// true.</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_floating_point</span><span class="str">&lt;char&gt;</span><span class="pun">::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// false.</span></pre>

<h4>
	is_enum
</h4>

<p>
	تعيد القيمة <code>true</code> بالنسبة لجميع أنواع التعدادات، بما في ذلك <code>‎enum class‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_158" style="">
<span class="kwd">enum</span><span class="pln"> fruit
</span><span class="pun">{</span><span class="pln">
    apple</span><span class="pun">,</span><span class="pln"> pair</span><span class="pun">,</span><span class="pln"> banana
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">enum</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> vegetable
</span><span class="pun">{</span><span class="pln">
    carrot</span><span class="pun">,</span><span class="pln"> spinach</span><span class="pun">,</span><span class="pln"> leek
</span><span class="pun">};</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_enum</span><span class="str">&lt;fruit&gt;</span><span class="pun">::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// true.</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_enum</span><span class="str">&lt;vegetable&gt;</span><span class="pun">::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// true.</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_enum</span><span class="str">&lt;int&gt;</span><span class="pun">::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// false.</span></pre>

<h4>
	is_pointer
</h4>

<p>
	تعيد القيمة <code>true</code> بالنسبة لجميع المؤشّرات:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_160" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_pointer</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">*&gt;::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// true.</span><span class="pln">
</span><span class="kwd">typedef</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="typ">MyPTR</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_pointer</span><span class="pun">&lt;</span><span class="typ">MyPTR</span><span class="pun">&gt;::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// true.</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_pointer</span><span class="str">&lt;int&gt;</span><span class="pun">::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// false.</span></pre>

<h4>
	is_class
</h4>

<p>
	تعيد القيمة <code>true</code> بالنسبة لجميع الأصناف والبنيات، باستثناء <code>‎enum class‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_162" style="">
<span class="kwd">struct</span><span class="pln"> FOO
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> BAR
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">enum</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> fruit
</span><span class="pun">{</span><span class="pln">
    apple</span><span class="pun">,</span><span class="pln"> pair</span><span class="pun">,</span><span class="pln"> banana
</span><span class="pun">};</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_class</span><span class="pun">&lt;</span><span class="pln">FOO</span><span class="pun">&gt;::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// true.</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_class</span><span class="pun">&lt;</span><span class="pln">BAR</span><span class="pun">&gt;::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// true.</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_class</span><span class="str">&lt;fruit&gt;</span><span class="pun">::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// false.</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_class</span><span class="str">&lt;int&gt;</span><span class="pun">::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// false.</span></pre>

<h2>
	تباين النوع المُعاد Return Type Covariance
</h2>

<p>
	يُقصَد بتباين نوع القيمة المعادة (Return Type Covariance) من تابع وهمي <code>m</code> السلوك الذي يصبح فيه نوع ذلك التابع (<code>T</code>) أكثر تحديداً عند إعادة تعريف <code>m</code> في صنف مشتق. ونتيجة لذلك، يتغيّر تحديد (specificity ) النوع <code>T</code> كما هو حال الصنف الذي يحتوي التابع <code>m</code>. انظر المثال التوضيحي التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_164" style="">
<span class="com">// 2. نسخة النتيجة المتباينة من المثال الأساسي، تحقق النوع الساكن.</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Top</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">virtual</span><span class="pln"> </span><span class="typ">Top</span><span class="pun">*</span><span class="pln"> clone</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pun">~</span><span class="typ">Top</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">  
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> D</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">Top</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln"> D</span><span class="pun">*</span><span class="pln"> </span><span class="com">/*← Covariant return */</span><span class="pln"> clone</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> override
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> D</span><span class="pun">(*</span><span class="kwd">this</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> DD</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> D
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> answer_ </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> answer</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> answer_</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    DD </span><span class="pun">*</span><span class="pln"> </span><span class="com">/*← Covariant return */</span><span class="pln"> clone</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> override
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> DD</span><span class="pun">(*</span><span class="kwd">this</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> std</span><span class="pun">;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    DD </span><span class="pun">*</span><span class="pln">p1 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> DD</span><span class="pun">();</span><span class="pln">
    DD </span><span class="pun">*</span><span class="pln">p2 </span><span class="pun">=</span><span class="pln"> p1</span><span class="pun">-&gt;</span><span class="pln">clone</span><span class="pun">();</span></pre>

<p>
	تحقق النوع الساكن يضمن النوع الديناميكي الصحيح DD لـ <code>p2*</code>، نتابع المثال …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_166" style="">
<span class="pln">    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> p2</span><span class="pun">-&gt;</span><span class="pln">answer</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">    </span><span class="com">// "42"</span><span class="pln">
    </span><span class="kwd">delete</span><span class="pln"> p2</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">delete</span><span class="pln"> p1</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	نتيجة المؤشّرات الذكية المتباينة
</h3>

<p>
	إليك المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_168" style="">
<span class="com">// 3. (نتيجة تباين المؤشر الذكي (تنظيف آلي.</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;memory&gt;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">unique_ptr</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Type</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> up</span><span class="pun">(</span><span class="typ">Type</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> unique_ptr</span><span class="pun">&lt;</span><span class="typ">Type</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">p</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Top</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">virtual</span><span class="pln"> </span><span class="typ">Top</span><span class="pun">*</span><span class="pln"> virtual_clone</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        unique_ptr</span><span class="pun">&lt;</span><span class="typ">Top</span><span class="pun">&gt;</span><span class="pln"> clone</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> up</span><span class="pun">(</span><span class="pln">virtual_clone</span><span class="pun">());</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">virtual</span><span class="pun">~</span><span class="typ">Top</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln"> 
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> D</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">Top</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln"> D </span><span class="pun">*</span><span class="pln"> </span><span class="com">/*← Covariant return */</span><span class="pln"> virtual_clone</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> override
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> D</span><span class="pun">(*</span><span class="kwd">this</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln"> unique_ptr</span><span class="pun">&lt;</span><span class="pln">D</span><span class="pun">&gt;</span><span class="pln"> </span><span class="com">/*← Apparent covariant return */</span><span class="pln"> clone</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> up</span><span class="pun">(</span><span class="pln">virtual_clone</span><span class="pun">());</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> DD</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> D
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> answer_ </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
    DD </span><span class="pun">*</span><span class="pln"> </span><span class="com">/*← Covariant return */</span><span class="pln"> virtual_clone</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> override
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> DD</span><span class="pun">(*</span><span class="kwd">this</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> answer</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> answer_</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    unique_ptr</span><span class="pun">&lt;</span><span class="pln">DD</span><span class="pun">&gt;</span><span class="pln"> </span><span class="com">/*← Apparent covariant return */</span><span class="pln"> clone</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> up</span><span class="pun">(</span><span class="pln">virtual_clone</span><span class="pun">());</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> std</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> p1 </span><span class="pun">=</span><span class="pln"> unique_ptr</span><span class="pun">&lt;</span><span class="pln">DD</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> DD</span><span class="pun">());</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> p2 </span><span class="pun">=</span><span class="pln"> p1</span><span class="pun">-&gt;</span><span class="pln">clone</span><span class="pun">();</span></pre>

<p>
	تحقق النوع الساكن يضمن النوع الديناميكي الصحيح DD لـ <code>p2*</code>، نتابع المثال …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_170" style="">
<span class="pln">    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> p2</span><span class="pun">-&gt;</span><span class="pln">answer</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">    </span><span class="com">// "42"</span><span class="pln">
    </span><span class="com">//  unique_ptr التنظيف يتم تلقائيا عبر المؤشر الحصري</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	مخطط أنواع الكائنات Layout of object types
</h2>

<h3>
	أنواع الأصناف
</h3>

<p>
	نعني بكلمة "صنف" (class)، أيّ نوع عُرِّف باستخدام الكلمة المفتاحية <code>‎class‎</code> أو <code>‎struct‎</code> (ولكن ليس بـ <code>‎enum struct‎</code> أو <code>‎enum ‎class‎</code>).
</p>

<ul>
<li>
		حتى إن كان الصنف فارغًا فإنه يحتلّ بايت واحدًا على الأقل في الذاكرة؛ ومن ثم سيتألف من الحشو (padding) فقط، هذا يضمن أنّه إذا أشار مؤشّر <code>‎p‎</code> إلى كائن من صنف فارغ، فإنّ <code>‎p + 1‎</code> ستكون عنوانًا مختلفًا وستشير إلى كائن مختلف. لكن يمكن أن يساوي حجم صنف فارغ القيمة 0 عند استخدامه كصنف أساسي. راجع: <a data-ss1617022768="1" href="https://en.cppreference.com/w/cpp/language/ebo" rel="external nofollow">تحسين الأصناف الأساسية الفارغة</a>.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_172" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Empty_1</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">    </span><span class="com">// sizeof(Empty_1)         == 1</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Empty_2</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">    </span><span class="com">// sizeof(Empty_2)         == 1</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Derived</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Empty_1</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">    </span><span class="com">// sizeof(Derived)         == 1</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">DoubleDerived</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Empty_1</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Empty_2</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">    </span><span class="com">// sizeof(DoubleDerived) == 1</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Holder</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Empty_1</span><span class="pln"> e</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">    </span><span class="com">// sizeof(Holder)         == 1</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">DoubleHolder</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Empty_1</span><span class="pln"> e1</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">Empty_2</span><span class="pln"> e2</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">    </span><span class="com">// sizeof(DoubleHolder)     == 2</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">DerivedHolder</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Empty_1</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Empty_1</span><span class="pln"> e</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">    </span><span class="com">// sizeof(DerivedHolder) == 2</span></pre>

<p>
	التمثيل الخاص بكائن صنف معيّن يحتوي تمثيل كائن الصنف الأساسي، وكذلك أنواع الأعضاء غير الساكنة (non-static member types). على سبيل المثال، في الصنف التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_174" style="">
<span class="kwd">struct</span><span class="pln"> S
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">*</span><span class="pln">y</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	يوجد تسلسل متتالي حجمه <code>‎sizeof(int)‎</code> بايت داخل كائن من النوع <code>‎S‎</code>، ويُطلق عليه "كائن فرعي" (subobject)، يحتوي قيمة <code>‎x‎</code>، إضافة إلى كائن فرعي آخر حجمه <code>‎sizeof(char*)‎</code> بايت ويحتوي قيمة <code>‎y‎</code>، ولا يمكن أن يتداخل الاثنان.
</p>

<ul>
<li>
		إذا كان لنوع صنف معيّن أعضاء و/أو أصناف أساسية من الأنواع <code>‎t1, t2,...tN‎</code>، فينبغي ألّا يقلّ الحجم عن <code>sizeof(t1) + sizeof(t2) + ... + sizeof(tN)‎</code> نظرًا للنقاط السابقة، لكن بناءً على متطلّبات المحاذاة الخاصّة بالأعضاء والأصناف الأساسية، فقد يضطر المٌصرّف إلى إدراج حشو بين الكائنات الفرعية، أو في بداية الكائن أو نهايته.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_176" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">AnInt</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// sizeof(AnInt)        == sizeof(int)</span><span class="pln">
</span><span class="com">// sizeof(AnInt) == 4 (4) :في أنظمة 32 أو 64 بت</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">TwoInts</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">,</span><span class="pln"> j</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// sizeof(TwoInts)        &gt;= 2* sizeof(int)</span><span class="pln">
</span><span class="com">// sizeof(TwoInts)         == 8 (4 + 4)  :في أنظمة 32 أو 64 بت</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">IntAndChar</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">char</span><span class="pln"> c</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// sizeof(IntAndChar)    &gt;= sizeof(int) + sizeof(char)</span><span class="pln">
</span><span class="com">// sizeof(IntAndChar)     == 8 (4 + 1 + padding)   :في أنظمة 32 أو 64 بت</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">AnIntDerived</span><span class="pun">:</span><span class="pln"> </span><span class="typ">AnInt</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> l</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// sizeof(AnIntDerived) &gt;= sizeof(AnInt) + sizeof(long long)</span><span class="pln">
</span><span class="com">// sizeof(AnIntDerived) == 16 (4 + padding + 8)  :في أنظمة 32 أو 64 بت</span></pre>

<ul>
<li>
		في حال إدراج الحشو في كائن بسبب متطلّبات المحاذاة، فإنّ الحجم سيكون أكبر من مجموع أحجام الأعضاء والأصناف الأساسية، أما إن كانت المحاذاة مؤلّفة من <code>‎n‎</code> بايت، فسيكون الحجم عادةً أصغر مضاعَف لـ‏ <code>‎n‎</code>، وهو أكبر من حجم جميع الأعضاء والأصناف الأساسية. كذلك سيوضع كل عضو <code>‎memN‎</code> في عنوان من مضاعفات <code>‎alignof(memN)‎</code>، وسيساوي <code>‎n‎</code> عادةً محاذاة العضو الذي له أكبر محاذاة.
	</li>
</ul>
<p>
	نتيجة لهذا، في حال أُتبِع عضوٌ بعضو آخر ذي محاذاة أكبر فهناك احتمال بأنّ العضو الأخير لن يُحاذى بشكل صحيح في حال وضعه مباشرة بعد العضو السابق، وهنا سيُوضع الحشو (المعروف أيضًا بمحاذاة العضو - alignment member) بين العضوين، بحيث يتيح للعضو الأخير أن يحصل على المحاذاة المرغوبة. بالمقابل، إذا أُتبِع عضو بعضوٍ آخر ذي محاذاة أصغر، فلن تكون هناك حاجة إلى الحشو، تُعرف هذه العملية أيضًا باسم "التعبئة" (packing).
</p>

<p>
	ونظرًا لأنّ الأصناف تشارك عادة محاذاة أعضائها مع أكبر محاذاة (largest alignof)، فستأخذ الأصناف عادةً محاذاة النوع المُضمن (built-in type) بشكل مباشر أو غير مباشر والذي له أكبر محاذاة. انظر المثال التالي:
</p>

<p>
	افترض أن <code>sizeof(short) == 2</code> و <code>sizeof(int) == 4</code> و <code>sizeof(long long) == 8</code>، وكذلك افترض تحديد محاذاة 4-بت للمصرِّف
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_178" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Char</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> c</span><span class="pun">;</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="com">// sizeof(Char)            == 1 (sizeof(char))</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Int</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln"> </span><span class="pun">};</span><span class="pln"> 
</span><span class="com">// sizeof(Int)                == 4 (sizeof(int))</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">CharInt</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> c</span><span class="pun">;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln"> </span><span class="pun">};</span><span class="pln"> 
</span><span class="com">// sizeof(CharInt)            == 8 (1 (char) + 3 (padding) + 4 (int))</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">ShortIntCharInt</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">short</span><span class="pln"> s</span><span class="pun">;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> c</span><span class="pun">;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> j</span><span class="pun">;</span><span class="pln"> </span><span class="pun">};</span><span class="pln"> 
</span><span class="com">// sizeof(ShortIntCharInt)        == 16 (2 (short) + 2 (padding) + 4 (int) + 1 (char) +</span><span class="pln">
</span><span class="com">//                        3 (padding) + 4 (int))</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">ShortIntCharCharInt</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">short</span><span class="pln"> s</span><span class="pun">;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> c</span><span class="pun">;</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> d</span><span class="pun">;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> j</span><span class="pun">;</span><span class="pln"> </span><span class="pun">};</span><span class="pln"> 
</span><span class="com">// sizeof(ShortIntCharCharInt)    == 16 (2 (short) + 2 (padding) + 4 (int) + 1 (char) +</span><span class="pln">
</span><span class="com">//                        1 (char) + 2 (padding) + 4 (int))</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">ShortCharShortInt</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">short</span><span class="pln"> s</span><span class="pun">;</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> c</span><span class="pun">;</span><span class="pln"> </span><span class="kwd">short</span><span class="pln"> t</span><span class="pun">;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln"> </span><span class="pun">};</span><span class="pln"> 
</span><span class="com">// sizeof(ShortCharShortInt)    == 12 (2 (short) + 1 (char) + 1 (padding) + 2 (short) +</span><span class="pln">
</span><span class="com">//                        2 (padding) + 4 (int))</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">IntLLInt</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> l</span><span class="pun">;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> j</span><span class="pun">;</span><span class="pln"> </span><span class="pun">};</span><span class="pln"> 
</span><span class="com">// sizeof(IntLLInt)            == 16 (4 (int) + 8 (long long) + 4 (int))</span><span class="pln">
</span><span class="com">// إذا لم تُحدَّد التعبئة بصراحة، فإنّ معظم المصرفات ستعبّئ هذا مع محاذاة من 8 بتات، بحيث</span><span class="pln">
</span><span class="com">// sizeof(IntLLInt)            == 24 (4 (int) + 4 (padding) + 8 (long long) +</span><span class="pln">
</span><span class="com">//                        4 (int) + 4 (padding))</span></pre>

<p>
	لتكن <code>sizeof(bool) == 1</code> و <code>sizeof(ShortIntCharInt) == 16</code>، و <code>sizeof(IntLLInt) == 24</code>، والمحاذاة الافتراضية: <code>alignof(ShortIntCharInt) == 4</code> و <code>alignof(IntLLInt) == 8</code>، نتابع المثال …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_180" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">ShortChar3ArrShortInt</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">short</span><span class="pln"> s</span><span class="pun">;</span><span class="pln">
 </span><span class="kwd">char</span><span class="pln"> c3</span><span class="pun">[</span><span class="lit">3</span><span class="pun">];</span><span class="pln">
 </span><span class="kwd">short</span><span class="pln"> t</span><span class="pun">;</span><span class="pln">
 </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// ShortChar3ArrShortInt لديه محاذاة 4 بت:    alignof(int) &gt;= alignof(char) &amp;&amp;</span><span class="pln">
</span><span class="com">//                        alignof(int) &gt;= alignof(short)</span><span class="pln">
</span><span class="com">// sizeof(ShortChar3ArrShortInt)    ==12 (2 (short) + 3 (char[3]) + 1 (padding) +</span><span class="pln">
</span><span class="com">//                        2 (short) + 4 (int))</span><span class="pln">
</span><span class="com">// موضوع عند المحاذاة 2 وليس 4 t لاحظ أنّ</span><span class="pln">
</span><span class="com">//                        alignof(short) == 2</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Large_1</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">ShortIntCharInt</span><span class="pln"> sici</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">bool</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">ShortIntCharInt</span><span class="pln"> tjdj</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="com">// تساوي 4 بتات Large_1 محاذاة</span><span class="pln">
 </span><span class="com">// alignof(ShortIntCharInt) == alignof(int) == 4</span><span class="pln">
 </span><span class="com">// alignof(b) == 1</span><span class="pln">
 </span><span class="com">// alignof(Large_1) == 4 وعليه تكون</span><span class="pln">
</span><span class="com">// sizeof(Large_1)        ==36 (16 (ShortIntCharInt) + 1 (bool) + 3 (padding) +</span><span class="pln">
</span><span class="com">//                    16 (ShortIntCharInt))</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Large_2</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">IntLLInt</span><span class="pln"> illi</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">float</span><span class="pln"> f</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">IntLLInt</span><span class="pln"> jmmj</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// تساوي 8 بتات Large_2 محاذاة</span><span class="pln">
 </span><span class="com">// alignof(IntLLInt) == alignof(long long) == 8</span><span class="pln">
 </span><span class="com">// alignof(float) == 4</span><span class="pln">
 </span><span class="com">// alignof(Large_2) == 8 وعليه</span><span class="pln">
</span><span class="com">// sizeof(Large_2) == 56 (24 (IntLLInt) + 4 (float) + 4 (padding) + 24 (IntLLInt))</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<ul>
<li>
		في حال فَرْض المحاذاة الصارمة عبر <code>‎alignas‎</code>، فسيُستخدَم الحشو لإجبار النوع على الالتزام بالمحاذاة المُحدّدة، حتى لو كان أصغر. في المثال أدناه، سيكون لـ <code>‎Chars&lt;5&gt;‎</code> ثلاث (أو ربّما أكثر) أُثمونات محشُوّة (padding bytes) مُدرَجة في النهاية لكي يبلغ الحجم الإجمالي 8 بتّات. لا يمكن لصنف محاذاته 4 أن يكون حجمه 5 لأنّه سيكون من المستحيل إنشاء مصفوفة من هذا الصنف، لذلك يجب "تقريب" الحجم إلى أحد مضاعفات العدد 4 عبر حشو البايتات.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_182" style="">
<span class="com">// ينبغي أن تكون محاذاة هذا النوع من مضاعفات 4، وينبغي إضافة الحشو عند الحاجة</span><span class="pln">
</span><span class="com">// Chars&lt;1&gt;..Chars&lt;4&gt; are 4 bytes, Chars&lt;5&gt;..Chars&lt;8&gt; are 8 bytes, etc.</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">size_t</span><span class="pln"> SZ</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> alignas</span><span class="pun">(</span><span class="lit">4</span><span class="pun">)</span><span class="pln"> </span><span class="typ">Chars</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">char</span><span class="pln"> arr</span><span class="pun">[</span><span class="pln">SZ</span><span class="pun">];</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">static_assert</span><span class="pun">(</span><span class="kwd">sizeof</span><span class="pun">(</span><span class="typ">Chars</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">&gt;)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="typ">Chars</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">4</span><span class="pun">&gt;),</span><span class="pln"> </span><span class="str">"Alignment is strict.\n"</span><span class="pun">);</span></pre>

<ul>
<li>
		<p>
			إذا كان لعضوين غير ساكنين من صنف معيّن نفس مُحدّد الوصول (access specifier)، فإنّ العضو المُصَرَّح عنه أخيرًا سيأتي آخرًا في تمثيل الكائن. ولكن إذا اختلفت مُحدّدات الوصول، فإنّ ترتيبَهما النسبي داخل الكائن سيكون غير مُحدّد.
		</p>
	</li>
	<li>
		<p>
			الترتيب الذي تظهر به الكائنات الفرعية للصنف الأساسي داخل الكائن غير محدّد، سواء أكانت ستظهر بالتتابع، أو ستظهر قبل أو بعد أو بين الكائنات العضوية الفرعية.
		</p>
	</li>
</ul>
<h3>
	الأنواع الحسابية Arithmetic types
</h3>

<h4>
	أنواع الأحرف الضيقة Narrow character types
</h4>

<p>
	يستخدِم نوع الحروف غير المؤشّرة <code>‎unsigned char‎</code> كل البتات لتمثيل عدد ثنائي (binary number). لذا إذا كان طول <code>‎unsigned char‎</code> يساوي 8 بتات، فإنّ كل الأنماط الممكن تمثيلها بـ 8 بتّات -والتي يبلغ عددها 256- للكائن <code>‎char‎</code> ستمثِّل 256 عددًا في المجال {0، 1، …، 255}. العدد 42 مثلا، سيُمثَّل بالسلسلة البتّية <code>‎00101010‎</code>.
</p>

<p>
	ليس هناك حشو للبتّات في نوع الأحرُف المؤشّرة <code>‎signed char‎</code>، أي أنّه إذا كان طول <code>‎signed char‎</code> يساوي 8 بتات، فسَيستخدم 8 بتات لتمثيل الأعداد. لاحظ أنّ هذه الضمانات لا تنطبق على الأنواع الأخرى.
</p>

<h4>
	أنواع الأعداد الصحيحة
</h4>

<p>
	تستخدم أنواع الأعداد الصحيحة غير المُؤشّرة نظامًا ثنائيًا خالصًا، لكنّها قد تحتوي على بتّات محشُوّة. على سبيل المثال، من الممكن -رغم بعداحتماله- أن يساوي طول عدد صحيح غير مؤشّر <code>‎unsigned int‎</code> ‏64 بتّة، لكن لن يكون بمقدوره تخزين الأعداد الصحيحة بين 0 و ‎‎232 - 1‎‎‎‎ (ضمنيّة)، لأنّ البتات الأخرى البالغ عددها 32 بتة ستكون عبارة عن بتّات حشو، وتلك لا ينبغي كتابتها مباشرة.
</p>

<p>
	تستخدم أنواع الأعداد الصحيحة المُؤشّرة نظامًا ثنائيًا يحتوي على بتّة مخصّصة للإشارة (بتّة الإشارة)، وربّما بتات محشوة. ويكون للقيم التي تنتمي إلى المجال المشترك بين نوع عددي صحيح مؤشّر ونوع عددي صحيح غير مؤشّر، يكون لها نفس التمثيل. على سبيل المثال، إذا كانت السلسلة البتّية <code>‎0001010010101011‎</code> لعدد صحيح قصير غير مؤشّر (<code>‎unsigned short‎</code>) تمثّل القيمة <code>‎5291‎</code>، فإنّها ستمثّل أيضًا القيمة <code>‎5291‎</code> عند تفسيرها كعدد قصير (short).
</p>

<p>
	ويحدد التنفيذ أنظمة التمثيل المستخدمة، سواء كانت المكمّل الثنائي (two's complement)، أو المكمّل الأحادي (one's complement)، أو تمثيل الإشارة-السعة (sign-magnitude)، لأنّ الأنظمة الثلاثة تفي بالمتطلّبات الواردة في الفقرة السابقة.
</p>

<h4>
	أنواع الأعداد العشرية Floating point types
</h4>

<p>
	يتعلق تمثيل أنواع الأعداد العشرية بالتنفيذ، ويتوافق النوعان الأكثر شيوعًا <code>‎float‎</code> و <code>‎double‎</code> مع توصيف IEEE 754، ويبلغ طولهما 32 و 64 بت (مثلًا، ستتألّف دقّة النوع <code>‎float‎</code> من ‏23 بت، مع 8 بتّات للأسّ، وبتّ واحدة للإشارة)، لكن المعيار لا يضمن أيّ شيء، ويعتري تمثيل الأعداد العشرية غالبًا بعض الثغرات، والتي تتسبّب بأخطاء عند استخدامها في العمليات الحسابية.
</p>

<h3>
	المصفوفات
</h3>

<p>
	ليس هناك حشو بين عناصر أنواع المصفوفات، لذا فالمصفوفة التي تحتوي عناصر من النوع <code>‎T‎</code> هي مجرد سلسلة من كائنات <code>‎T‎</code> متجاورة في الذاكرة بالترتيب، والمصفوفات متعدّدة الأبعاد هي مصفوفات مكوّنة من مصفوفات، وينطبق عليها ما سبق تكراريًا.
</p>

<p>
	على سبيل المثال، إذا كان لدينا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_184" style="">
<span class="typ">int</span><span class="pln"> a</span><span class="pun">[</span><span class="lit">5</span><span class="pun">][</span><span class="lit">3</span><span class="pun">];</span></pre>

<p>
	فتكون <code>‎a‎</code> مصفوفة من 5 مصفوفات ثلاثية تحتوي أعدادًا صحيحة (<code>‎int‎</code>)، لذا فإنّ <code>‎‎‎‎a[0]‎</code> التي تتكون من العناصر الثلاثة <code>a[0][0]‎</code> و <code>a[0][1]‎</code> و <code>a[0][2]‎</code>، توضع في الذاكرة قبل <code>‎‎‎‎a[1]‎</code>، التي تتكوّن من <code>a[1][0]‎</code> و <code>a[1][1]‎</code> و <code>a[1][2]‎</code>. ويُسمّى هذا النظام بالترتيب الكبير للصفوف (row major order).
</p>

<h2>
	استنباط النوع Type Inference
</h2>

<p>
	يناقش هذا الموضوع استنباط النوع ويشمل الكلمة المفتاحية <code>‎auto‎</code> المتاحة منذ الإصدار C++‎ 11.
</p>

<h3>
	نوع البيانات: Auto
</h3>

<p>
	يوضّح هذا المثال استنباطات النوع الأساسية التي يمكن للمٌصرّف القيام بها.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_186" style="">
<span class="kwd">auto</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// a = int</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2u</span><span class="pun">;</span><span class="pln"> </span><span class="com">// b = unsigned int</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">a</span><span class="pun">;</span><span class="pln"> </span><span class="com">// c = int*</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> d </span><span class="pun">=</span><span class="pln"> c</span><span class="pun">;</span><span class="pln"> </span><span class="com">// d = const int*</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pun">&amp;</span><span class="pln"> e </span><span class="pun">=</span><span class="pln"> b</span><span class="pun">;</span><span class="pln"> </span><span class="com">// e = const unsigned int&amp;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> b </span><span class="com">// x = int, #compiler warning unsigned and signed</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> v </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pun">;</span><span class="pln"> </span><span class="com">// v = std::vector&lt;int&gt;</span></pre>

<p>
	لا تنجح الكلمة المفتاحية <code>auto</code> دائمًا في استنباط النوع المتوقع إذا لم تُعطَ تلميحات إضافية بخصوص <code>‎&amp;‎</code> أو <code>‎const‎</code> أو <code>‎constexpr‎</code>. في المثال التالي حيث <code>y</code> تساوي <code>unsigned int</code>، لاحظ أننا لا نستطيع استنباط أن <code>y</code> من نوع <code>&amp;const unsigned int</code>، وكان المترجم سينتج نسخة بدلًا من قيمة مرجعية إلى <code>e</code> أو <code>b</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_188" style="">
<span class="kwd">auto</span><span class="pln"> y </span><span class="pun">=</span><span class="pln"> e</span><span class="pun">;</span></pre>

<h3>
	Lambda auto
</h3>

<p>
	يمكن استخدام الكلمة المفتاحية <code>auto</code> للتصريح عن <a data-ss1617022768="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-39-%D8%AF%D9%88%D8%A7%D9%84-%D9%84%D8%A7%D9%85%D8%AF%D8%A7-lambdas-%D9%81%D9%8A-cpp-r960/" rel="">دوالّ لامدا</a>، إذ تساعد على اختصار الشيفرة اللازمة للتصريح عن مؤشّر دالّة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_190" style="">
<span class="kwd">auto</span><span class="pln"> </span><span class="typ">DoThis</span><span class="pln"> </span><span class="pun">=[](</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	هذا إن كان <code>Do this</code> من نوع (int)(*DoThis)(int, int)، وإلا فنكتب ما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_192" style="">
<span class="typ">int</span><span class="pun">(*</span><span class="pln">pDoThis</span><span class="pun">)(</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=[](</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Dothis</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">);</span><span class="pln">    </span><span class="com">//      c = int</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> d </span><span class="pun">=</span><span class="pln"> pDothis</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">);</span><span class="pln">    </span><span class="com">//      d = int</span><span class="pln">
</span><span class="com">//      يختصر تعريف دوال لامدا 'auto' استخدام</span></pre>

<p>
	السلوك الافتراضي إذا لم يُعرَّف نوع القيمة المُعادة لدوال لامدا، هو استنباطها تلقائيًا من عبارة <code>return</code>. في المثال التالي، الأسطر الثلاث التالية متكافئة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_194" style="">
<span class="pun">[](</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">;</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="pun">[](</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">;</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="pun">[](</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">;</span><span class="pln"> </span><span class="pun">};</span></pre>

<h3>
	الحلقات و auto
</h3>

<p>
	يوضّح هذا المثال كيف يمكن استخدام <code>auto</code> لاختصار تصريح أنواع حلقات <code>for</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_196" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">map</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&gt;</span><span class="pln"> </span><span class="typ">Map</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> pair</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Map</span><span class="pun">)</span><span class="pln">    </span><span class="com">//      pair = std::pair&lt;int, std::string&gt;</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> pair</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Map</span><span class="pun">)</span><span class="pln">    </span><span class="com">//      pair = const std::pair&lt;int, std::string &gt;       </span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">pair</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Map</span><span class="pun">)</span><span class="pln">    </span><span class="com">//      pair = const std::pair&lt;int, std::string&gt;&amp;</span><span class="pln">
            </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i</span><span class="pun">)</span><span class="pln">    </span><span class="com">//      i = int</span><span class="pln">
                </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Map</span><span class="pun">.</span><span class="pln">size</span><span class="pun">();</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i</span><span class="pun">)</span><span class="pln">    </span><span class="com">//    size_t وليس i = int لاحظ أنّ   </span><span class="pln">
                    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Map</span><span class="pun">.</span><span class="pln">size</span><span class="pun">();</span><span class="pln"> i </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> </span><span class="pun">--</span><span class="pln">i</span><span class="pun">)</span><span class="pln">    </span><span class="com">//      i = size_t</span></pre>

<h2>
	استنتاج الأنواع type deduction
</h2>

<h3>
	استنتاج مُعامل القالب الخاص بالمنشئات
</h3>

<p>
	لم يكن بمقدور "استنتاج القالب" (template deduction) قبل الإصدار C++‎ 17 أن يستنتج نوع الصنف في مُنشئ، بل كان يجب تحديده بشكل صريح، وبما أن تسمية تلك الأنواع مرهقة أحيانًا أو (في حال تعبيرات لامدا) مستحيلة، فقد وُجِدت عدّة مصانع للأنواع (مثل <code>‎make_pair()‎</code> و <code>‎make_tuple()‎</code> و <code>‎back_inserter()‎</code> وما إلى ذلك).
</p>

<p>
	<strong>الإصدار ≥ C++‎ 17</strong>
</p>

<p>
	غير أن هذا لم يُعدّ هذا ضروريًا بعد الآن:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_198" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">pair p</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4.5</span><span class="pun">);</span><span class="pln">    </span><span class="com">// std::pair&lt;int, double&gt;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">tuple t</span><span class="pun">(</span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2.5</span><span class="pun">);</span><span class="pln">    </span><span class="com">// std::tuple&lt;int, int, double&gt;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">copy_n</span><span class="pun">(</span><span class="pln">vi1</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">back_insert_iterator</span><span class="pun">(</span><span class="pln">vi2</span><span class="pun">));</span><span class="pln">    </span><span class="com">// back_insert_iterator&lt;std::vector &lt; int&gt;&gt; إنشاء</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">lock_guard lk</span><span class="pun">(</span><span class="pln">mtx</span><span class="pun">);</span><span class="pln">    </span><span class="com">// std::lock_guard &lt; decltype(mtx)&gt;</span></pre>

<p>
	يُتوقّع من المُنشئات استنتاج معامِلات قالب الصنف (class template parameters)، لكن هذا قد لا يكفي أحيانًا، لذا يمكننا تقديم بعض التوجيهات الصريحة لتسهيل الاستنتاج:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_200" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Iter</span><span class="pun">&gt;</span><span class="pln">
</span><span class="typ">vector</span><span class="pun">(</span><span class="typ">Iter</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Iter</span><span class="pun">)</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">vector</span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> iterator_traits</span><span class="pun">&lt;</span><span class="typ">Iter</span><span class="pun">&gt;::</span><span class="pln">value_type</span><span class="pun">&gt;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> array</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">};</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> v</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">begin</span><span class="pun">(</span><span class="pln">array</span><span class="pun">),</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">end</span><span class="pun">(</span><span class="pln">array</span><span class="pun">));</span><span class="pln">   </span><span class="com">// std::vector &lt; int&gt; استنتاج</span></pre>

<h3>
	استنتاج النوع عبر Auto
</h3>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	يعمل استنتاج النوع باستخدام الكلمة المفتاحية <code>‎auto‎</code> بطريقة مشابهة لاستنتاج نوع القالب (Template Type Deduction). انظر الأمثلة التالية:
</p>

<p>
	<code>x</code> في الشيفرة أدناه ليست لا مؤشرًا ولا مرجعًا، بل هي من النوع <code>int</code>، و<code>cx</code> ليست هذا ولا ذاك أيضًا، وإنما هي من نوع <code>const int</code>، بينما تكون <code>rx</code> مرجعًا غير عام (non-universal)، فهي مرجع إلى ثابت. انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_202" style="">
<span class="kwd">auto</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">27</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> cx </span><span class="pun">=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">    
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pun">&amp;</span><span class="pln"> rx </span><span class="pun">=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">  </span></pre>

<p>
	وفي الشيفرة أدناه، تكون <code>x</code> عددًا صحيحًا <code>int</code> وقيمة يسارية أيضًا <code>lvalue</code>، وعليه يكون نوع <code>uref1</code> هو <code>&amp;int</code>، وبالمثل فإن <code>cx</code> نوعها <code>const int</code> وقيمة يسارية، لذا يكون <code>uref2</code> من نوع <code>&amp; const int</code>. أما <code>27</code> فهي عدد صحيح وقيمة يسارية، لذا يكون <code>uref3</code> من نوع <code>&amp;&amp;int</code>. انظر ..
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_204" style="">
<span class="kwd">auto</span><span class="pun">&amp;&amp;</span><span class="pln"> uref1 </span><span class="pun">=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pun">&amp;&amp;</span><span class="pln"> uref2 </span><span class="pun">=</span><span class="pln"> cx</span><span class="pun">;</span><span class="pln">    
</span><span class="kwd">auto</span><span class="pun">&amp;&amp;</span><span class="pln"> uref3 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">27</span><span class="pun">;</span><span class="pln">    </span></pre>

<p>
	الاختلافات بين المثالين السابقين مُوضّحة أدناه: يكون نوع <code>x1</code> و <code>x2</code> هو <code>int</code> وقيمتهما <code>27</code>، أما <code>x3</code> و <code>x4</code> فنوعهما <code>&lt;std::initializer_list&lt;int</code> وقيمة كل منهما <code>{ 27 }</code>. قد يُستنتج النوع في بعض المصرِّفات على أنه <code>int</code> مع قيمة تساوي <code>27</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_206" style="">
<span class="kwd">auto</span><span class="pln"> x1 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">27</span><span class="pun">;</span><span class="pln">  
</span><span class="kwd">auto</span><span class="pln"> x2</span><span class="pun">(</span><span class="lit">27</span><span class="pun">);</span><span class="pln">    
</span><span class="kwd">auto</span><span class="pln"> x3 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="lit">27</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> x4</span><span class="pun">{</span><span class="pln"> </span><span class="lit">27</span><span class="pln"> </span><span class="pun">};</span><span class="pln"> 

</span><span class="kwd">auto</span><span class="pln"> x5 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2.0</span><span class="pln"> </span><span class="pun">}</span><span class="pln">    </span><span class="com">// error! can't deduce T for std::initializer_list &lt; t&gt;</span></pre>

<p>
	إذا استخدمت مُهيّئات الأقواس المعقوصة (braced initializers)، فسيُفرض على <code>auto</code> إنشاء متغيّر من النوع <code>std::initializer_list&lt;T&gt;‎</code>، وإذا لم يكن من الممكن استنتاج <code>‎T‎</code>، فستُرفض الشيفرة.
</p>

<p>
	عندما تُستخدَم <code>‎auto‎</code> كنوع القيمة المُعادة من دالّة، فإنّ نوع الإعادة سيكون زائدًا (trailing return type).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_208" style="">
<span class="kwd">auto</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
 </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 14</strong>
</p>

<p>
	يسمح الإصدار C++‎ 14، بالإضافة إلى استخدام <code>auto</code> المسموح بها في C++‎ 11، بما يلي:
</p>

<ol>
<li>
		عند استخدامها كنوع للقيمة المُعادة من دالة بدون نوع إعادة زائد (trailing return type)، فإنّها تشير إلى أنّ النوع المُعاد من الدالة يجب أن يُستنتَج من تعليمات الإعادة في متن الدالّة، إن وُجِدت.
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_210" style="">
<span class="com">// int تعيد f </span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> 

</span><span class="com">// void تعيد g </span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> g</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"hello, world!\n"</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span></pre>

<ol start="2">
<li>
		عند استخدامها مع نوع مُعامل خاص بتعبير لامدا، فإنّها تشير إلى أنّ لامدا عامّة (generic). في المثال أدناه تكون <code>x</code> من نوع <code>const int</code> وقيمتها 126.
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_212" style="">
<span class="kwd">auto</span><span class="pln"> triple </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[](</span><span class="kwd">auto</span><span class="pln"> x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">3</span><span class="pun">*</span><span class="pln">x</span><span class="pun">;</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> triple</span><span class="pun">(</span><span class="lit">42</span><span class="pun">);</span><span class="pln"> </span></pre>

<p>
	يستنتج الشكل الخاصّ <code>‎decltype(auto)‎</code> النوع باستخدام قواعد استنتاج النوع في <code>‎decltype‎</code>، وليس قواعد <code>‎auto‎</code>. في المثال التالي، <code>x</code> عدد صحيح، و <code>y</code> مرجع إلى <code>p*</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_214" style="">
<span class="typ">int</span><span class="pun">*</span><span class="pln"> p </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">int</span><span class="pun">(</span><span class="lit">42</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p</span><span class="pun">;</span><span class="pln"> 
</span><span class="kwd">decltype</span><span class="pun">(</span><span class="kwd">auto</span><span class="pun">)</span><span class="pln"> y </span><span class="pun">=</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p</span><span class="pun">;</span><span class="pln">  </span></pre>

<p>
	في C++‎ 03 والإصدارات الأقدم، كان للكلمة المفتاحية <code>‎auto‎</code> معنى مختلف تمامًا، إذ كانت مُحدِّد صنف تخزين (storage class specifier)، وقد ورِثتها من C.
</p>

<h3>
	استنتاج نوع القالب
</h3>

<p>
	الصيغة العامة للقالب:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_216" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">ParamType</span><span class="pln"> param</span><span class="pun">);</span><span class="pln">
f</span><span class="pun">(</span><span class="pln">expr</span><span class="pun">);</span></pre>

<p>
	الحالة 1: إذا كان <code>‎ParamType‎</code> مرجعًا أو مؤشّرًا، ولم يكن مرجعًا عامًا (Universal) أو لاحقًا (Forward). فسيعمل استنتاج النوع بالطريقة التالية: سيتجاهل المُصرّف جزء المرجع إذا كان موجودًا في <code>‎expr‎</code>، وسيحاول المُصرّف بعد ذلك مطابقة <code>‎expr‎</code> الخاص بالنوع مع <code>‎ParamType‎</code> لتحديد <code>‎T‎</code>. في المثال التالي يكون <code>param</code> مرجعًا، و<code>x</code> من نوع <code>int</code>، و<code>cx</code> من نوع <code>const int</code>، أما <code>rx</code> فهو مرجع إلى <code>x</code> كـ <code>const int</code>، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_218" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">T</span><span class="pun">&amp;</span><span class="pln"> param</span><span class="pun">);</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">27</span><span class="pun">;</span><span class="pln"> 
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> cx </span><span class="pun">=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">    
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&amp;</span><span class="pln"> rx </span><span class="pun">=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">   </span></pre>

<p>
	وفي بقية المثال أدناه، في حالة <code>(f(x</code> تكون <code>T</code> عددًا صحيحًا، ونوع <code>param</code> هو <code>&amp;int</code>، أما في السطرين الثاني والثالث، تكون <code>T</code> من نوع <code>const int</code> و <code>param</code> من نوع <code>&amp;const int</code>، انظر …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_220" style="">
<span class="pln">f</span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span><span class="pln">   
f</span><span class="pun">(</span><span class="pln">cx</span><span class="pun">);</span><span class="pln">    
f</span><span class="pun">(</span><span class="pln">rx</span><span class="pun">);</span><span class="pln">    </span></pre>

<p>
	الحالة 2: إذا كان <code>‎ParamType‎</code> مرجع عامًا أو مرجعًا لاحقًا، فسيكون استنتاج النوع مماثلًا لاستنتاج النوع في الحالة 1 إن كانت <code>‎expr‎</code> عبارة عن <a data-ss1617022768="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-40-%D9%81%D8%A6%D8%A7%D8%AA-%D8%A7%D9%84%D9%82%D9%8A%D9%85-value-categories-%D9%81%D9%8A-cpp-r969/" rel="">قيمة يمينية</a>. أمّا إذا كانت <code>‎expr‎</code> قيمة يسارية، فسيُستنتَج أنّ <code>‎T‎</code> و <code>‎ParamType‎</code> مرجعان يساريان. انظر المثال التالي حيث يكون <code>param</code> مرجعًا عامًا، و<code>x</code> من نوع <code>int</code>، و<code>cx</code> من نوع <code>const int</code>، و <code>rx</code> مرجع إلى <code>x</code> كـ <code>const int</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_222" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">T</span><span class="pun">&amp;&amp;</span><span class="pln"> param</span><span class="pun">);</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">27</span><span class="pun">;</span><span class="pln"> 
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> cx </span><span class="pun">=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">   
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&amp;</span><span class="pln"> rx </span><span class="pun">=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln"> </span></pre>

<p>
	في بقية المثال أدناه،
</p>

<ul>
<li>
		<code>(f(x</code>: تكون <code>x</code> قيمة يسارية وعليه فإن <code>T</code> و <code>param</code> يكون نوعهما <code>&amp;int</code>.
	</li>
	<li>
		<code>(f(cx</code>: تكون <code>cx</code> قيمة يسارية وعليه فإن <code>T</code> و <code>param</code> يكون نوعهما <code>&amp;const int</code>.
	</li>
	<li>
		<code>(f(rx</code>: تكون <code>rx</code> قيمة يسارية وعليه فإن <code>T</code> و <code>param</code> يكون نوعهما <code>&amp;const int</code>.
	</li>
	<li>
		<code>(f(27</code>: تكون <code>27</code> قيمة يمينية وعليه فإن <code>T</code> تكون <code>int</code> ومن ثم فإن <code>param</code> يكون نوعها <code>&amp;&amp;int</code>.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_224" style="">
<span class="pln">f</span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span><span class="pln">    
f</span><span class="pun">(</span><span class="pln">cx</span><span class="pun">);</span><span class="pln">   
f</span><span class="pun">(</span><span class="pln">rx</span><span class="pun">);</span><span class="pln">    
f</span><span class="pun">(</span><span class="lit">27</span><span class="pun">);</span><span class="pln">   </span></pre>

<p>
	الحالة 3: في حال لم يكن <code>‎ParamType‎</code> لا مؤشّرًا ولا مرجعًا، فإذا كانت <code>‎expr‎</code> مرجعًا أو ثابتةً، فسيُتجاهَل جزء المرجع، أمّا إذا كانت متغيّرة (volatile)، فسيُتجاهَل هذا أيضًا عند استنتاج نوع T. في المثال التالي: تُمرَّر <code>param</code> بالقيمة، وتكون <code>x</code> عددًا صحيحًا <code>int</code>، و<code>cx</code> تكون <code>const int</code>، بينما تكون <code>rx</code> مرجعًا إلى <code>x</code> كـ <code>const int</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_226" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">T param</span><span class="pun">);</span><span class="pln">  
</span><span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">27</span><span class="pun">;</span><span class="pln">    
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> cx </span><span class="pun">=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&amp;</span><span class="pln"> rx </span><span class="pun">=</span><span class="pln"> x</span><span class="pun">;</span></pre>

<p>
	في بقية المثال أدناه، يكون كل من <code>T</code> و <code>param</code> نوعهما <code>int</code>.
</p>

<pre class="ipsCode">
f(x);   
f(cx);    
f(rx);    
</pre>

<h3>
	نوع الإعادة الزائد Trailing return type
</h3>

<h4>
	تجنّب تأهيل اسم نوع مُتشعِّب
</h4>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_228" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">ClassWithAReallyLongName</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Iterator</span><span class="pln">
        </span><span class="pun">{</span><span class="pln"> </span><span class="com">/*... */</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
    </span><span class="typ">Iterator</span><span class="pln"> end</span><span class="pun">();</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	تعريف العضو <code>‎end‎</code> بنوع إعادة زائد (trailing return type):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_230" style="">
<span class="kwd">auto</span><span class="pln"> </span><span class="typ">ClassWithAReallyLongName</span><span class="pun">::</span><span class="pln">end</span><span class="pun">()-&gt;</span><span class="typ">Iterator</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">Iterator</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تعريف العضو <code>‎end‎</code> بدون نوع إعادة زائد:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_232" style="">
<span class="typ">ClassWithAReallyLongName</span><span class="pun">::</span><span class="typ">Iterator</span><span class="pln"> </span><span class="typ">ClassWithAReallyLongName</span><span class="pun">::</span><span class="pln">end</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">Iterator</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يُبحَثُ عن نوع الإعادة الزائد في نطاق الصنف (scope of the class)، بينما يُبحث عن نوع الإعادة البادئ (leading return type) في نطاق فضاء الاسم (namespace) المحيط، لذا قد يتطّلب ذلك إجراءَ تأهيل "مُكرّر" (redundant qualification).
</p>

<h4>
	تعبيرات لامدا Lambda expressions
</h4>

<p>
	لا يكون تعبير لامدا إلا نوع إعادة زائد فقط؛ إذ أنّ صيغة نوع الإعادة البادئ لا يمكن تطبيقها على دوالّ لامدا، لاحظ أنّه من غير الضروري غالبًا تحديد النوع المُعاد لأجل دالة لامدا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_234" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Derived1</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Derived2</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> lambda </span><span class="pun">=[](</span><span class="kwd">bool</span><span class="pln"> b</span><span class="pun">)-&gt;</span><span class="typ">Base</span><span class="pln"> </span><span class="pun">*</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">b</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Derived1</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">else</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Derived2</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// auto lambda = Base*[](bool b) { ... }; صيغة سيئة</span></pre>

<h2>
	Typedef والأسماء البديلة للأنواع
</h2>

<p>
	يمكن استخدام الكلمتين المفتاحيتين <code>‎typedef‎</code> و (منذ C++‎ 11)‏ <code>‎using‎</code> لإعطاء اسم جديد لنوع موجود.
</p>

<h3>
	أساسيات صياغة typedef
</h3>

<p>
	تصريح <code>‎typedef‎</code> يشبه التصريح عن متغيّر أو دالّة، غير أنّها تحتوي كلمة <code>‎typedef‎</code>، ويؤدّي وجودها إلى التصريح عن نوع بدلاً من التصريح عن متغيّر أو دالّة. انظر المثال التالي: في السطر التالي، <code>T</code> نوعه <code>int</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_242" style="">
<span class="typ">int</span><span class="pln"> T</span><span class="pun">;</span><span class="pln"> </span></pre>

<p>
	وهنا يكون <code>T</code> اسمًا بديلًا أو كُنية (alias) لـ <code>int</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_244" style="">
<span class="kwd">typedef</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> T</span><span class="pun">;</span></pre>

<p>
	نوع <code>A</code> "مصفوفة من 100 عدد صحيح:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_246" style="">
<span class="typ">int</span><span class="pln"> A</span><span class="pun">[</span><span class="lit">100</span><span class="pun">];</span></pre>

<p>
	أما هنا فيكون <code>A</code> اسمًا بديلًا للنوع "مصفوفة من 100 عدد صحيح":
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_248" style="">
<span class="kwd">typedef</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> A</span><span class="pun">[</span><span class="lit">100</span><span class="pun">];</span></pre>

<p>
	ونستطيع استخدام الاسم البديل للنوع بالتبادل مع الاسم الأصلي للنوع بمجرد تمام تعريف الأول. انظر المثال التالي حيث تكون <code>S</code> بُنية تحتوي مصفوفة من 100 عدد صحيح:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_250" style="">
<span class="kwd">typedef</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> A</span><span class="pun">[</span><span class="lit">100</span><span class="pun">];</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> S
</span><span class="pun">{</span><span class="pln">
    A data</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	لا تنشئ <code>‎typedef‎</code> نوعًا مختلفًا، بل تعطينا وسيلة أخرى للإشارة إلى نوع موجود سلفًا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_252" style="">
<span class="kwd">struct</span><span class="pln"> S
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">typedef</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> I</span><span class="pun">;</span><span class="pln">
I S</span><span class="pun">::</span><span class="pln">f</span><span class="pun">(</span><span class="pln">I x</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	استخدامات متقدّمة للكلمة المفتاحية typedef
</h3>

<p>
	بما أن تصريحات <code>typedof</code> لها نفس بنية تصريح المتغيرات العادية والدوال، فيمكن استخدام ذلك لقراءة وكتابة تصريحات أعقد. انظر المثال التالي حيث يكون نوع <code>f</code> في السطر الأول مؤشر إلى دالة تأخذ عددا صحيحا وتعيد <code>void</code>، بينما يكون في السطر الثاني اسمًا بديلًا للمؤشر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_254" style="">
<span class="kwd">void</span><span class="pun">(*</span><span class="pln">f</span><span class="pun">)(</span><span class="typ">int</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">typedef</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">(*</span><span class="pln">f</span><span class="pun">)(</span><span class="typ">int</span><span class="pun">);</span></pre>

<p>
	هذا مفيد بشكل خاص للبنيات ذات الصياغة المُربِكة، مثل المؤشّرات التي تشير إلى أعضاء غير ساكنة. انظر المثال التالي حيث يكون نوع <code>pmf</code> في السطر الأول مؤشرًا إلى دالة تابعة لـ <code>Foo</code>، يأخذ عددًا صحيحًا ويعيد <code>void</code>، بينما يكون في السطر الثاني اسمًا بديلًا للمؤشر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_256" style="">
<span class="kwd">void</span><span class="pun">(</span><span class="typ">Foo</span><span class="pun">::</span><span class="pln"> </span><span class="pun">*</span><span class="pln">pmf</span><span class="pun">)(</span><span class="typ">int</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">typedef</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">(</span><span class="typ">Foo</span><span class="pun">::</span><span class="pln"> </span><span class="pun">*</span><span class="pln">pmf</span><span class="pun">)(</span><span class="typ">int</span><span class="pun">);</span></pre>

<p>
	صيغة تصريحات الدوال التالية صعبة التذكر حتى للمبرمجين ذوي الخبرة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_258" style="">
<span class="kwd">void</span><span class="pun">(</span><span class="typ">Foo</span><span class="pun">::</span><span class="pln"> </span><span class="pun">*</span><span class="typ">Foo</span><span class="pun">::</span><span class="pln">f</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">*))(</span><span class="typ">int</span><span class="pun">);</span><span class="pln">
</span><span class="typ">int</span><span class="pun">(&amp;</span><span class="pln">g</span><span class="pun">())[</span><span class="lit">100</span><span class="pun">];</span></pre>

<p>
	ويمكن استخدام <code>‎typedef‎</code> لتسهيل قراءة الشيفرة كما في المثال التالي، حيث تكون <code>pmf</code> مؤشرًا إلى نوع دالة تابعة، و <code>f</code> هي دالة تابعة لـ <code>Foo</code>، و <code>ra</code> هي اختصار يعني "مرجع إلى مصفوفة" تتكون في حالتنا هنا من 100 عدد صحيح، وتعيد <code>g</code> مرجعًا إلى مصفوفة من 100 عدد صحيح أيضًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_260" style="">
<span class="kwd">typedef</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">(</span><span class="typ">Foo</span><span class="pun">::</span><span class="pln">pmf</span><span class="pun">)(</span><span class="typ">int</span><span class="pun">);</span><span class="pln">  
pmf </span><span class="typ">Foo</span><span class="pun">::</span><span class="pln">f</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">*);</span><span class="pln">   
</span><span class="kwd">typedef</span><span class="pln"> </span><span class="typ">int</span><span class="pun">(&amp;</span><span class="pln">ra</span><span class="pun">)[</span><span class="lit">100</span><span class="pun">];</span><span class="pln">  
ra g</span><span class="pun">();</span><span class="pln">  </span></pre>

<h3>
	التصريح عن عدّة أنواع باستخدام typedef
</h3>

<p>
	تُعدُّ الكلمة المفتاحية <code>‎typedef‎</code> مُحدِّدًا (speciﬁer)، لذا فهي تُطبّق بشكل منفصل على كل مُصرِّح (declarator)، وعليه يشير كل اسم مُصرّح به إلى النوع الذي سيكون لذلك الاسم في غياب <code>‎typedef‎</code>. انظر المثال التالي حيث يكون نوع <code>x</code> هو <code>*int</code> ونوع <code>p</code> هو <code>()(*)int</code>، أما في السطر التالي فيكون <code>x</code> اسمًا بديلًا لـ <code>*int</code>، و <code>p</code> اسم بديل لـ <code>()(*)int</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_262" style="">
<span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> </span><span class="pun">(*</span><span class="pln">p</span><span class="pun">)();</span><span class="pln">
</span><span class="kwd">typedef</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> </span><span class="pun">(*</span><span class="pln">p</span><span class="pun">)();</span><span class="pln"> </span></pre>

<h3>
	التصريح عن الاسم البديل عبر using
</h3>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	صيغة <code>‎using‎</code> بسيطة للغاية، إذ يوضع الاسم المُراد تعريفه على الجانب الأيسر، بينما يوضع التعريف على الجانب الأيمن.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_264" style="">
<span class="kwd">using</span><span class="pln"> I </span><span class="pun">=</span><span class="pln"> </span><span class="typ">int</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> A </span><span class="pun">=</span><span class="pln"> </span><span class="typ">int</span><span class="pun">[</span><span class="lit">100</span><span class="pun">];</span><span class="pln">    </span><span class="com">//مصفوفة من 100 عدد صحيح  </span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> FP </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">(*)(</span><span class="typ">int</span><span class="pun">);</span><span class="pln">    </span><span class="com">// void يعيد  int مؤشر إلى دالة من</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> MP </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">(</span><span class="typ">Foo</span><span class="pun">::</span><span class="pln"> </span><span class="pun">*)(</span><span class="typ">int</span><span class="pun">);</span><span class="pln">    </span><span class="com">// void ويعيد int  يأخذ Foo مؤشر إلى دالة تابعة من</span></pre>

<p>
	إنشاء اسم بديل للنوع باستخدام <code>‎using‎</code> له نفس تأثير إنشاء اسم بديل للنوع باستخدام <code>‎typedef‎</code>، فما هي إلا صيغة بديلة لإنجاز نفس الشيء. وعلى عكس <code>‎typedef‎</code>، فإنّ <code>‎using‎</code> قد تكون مُقولَبة، ويُستخدم مصطلح قالب الاسم البديل "alias template" للإشارة إلى "typedef المُقولبة" (template typedef) والمُنشأة عبر <code>‎using‎</code>.
</p>

<h2>
	نوع الإعادة الزائد Trailing return type
</h2>

<h3>
	تجنّب تأهيل اسم نوع مُتشعِّب
</h3>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_266" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">ClassWithAReallyLongName</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Iterator</span><span class="pln">
        </span><span class="pun">{</span><span class="pln"> </span><span class="com">/*... */</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
    </span><span class="typ">Iterator</span><span class="pln"> end</span><span class="pun">();</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	تعريف العضو <code>‎end‎</code> بنوع إعادة زائد (trailing return type):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_268" style="">
<span class="kwd">auto</span><span class="pln"> </span><span class="typ">ClassWithAReallyLongName</span><span class="pun">::</span><span class="pln">end</span><span class="pun">()-&gt;</span><span class="typ">Iterator</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">Iterator</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تعريف العضو <code>‎end‎</code> بدون نوع إعادة زائد:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_270" style="">
<span class="typ">ClassWithAReallyLongName</span><span class="pun">::</span><span class="typ">Iterator</span><span class="pln"> </span><span class="typ">ClassWithAReallyLongName</span><span class="pun">::</span><span class="pln">end</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">Iterator</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يُبحَثُ عن نوع الإعادة الزائد في نطاق الصنف (scope of the class)، بينما يُبحث عن نوع الإعادة البادئ (leading return type) في نطاق فضاء الاسم (namespace) المحيط، لذا قد يتطّلب ذلك إجراءَ تأهيل "مُكرّر" (redundant qualification).
</p>

<h3>
	تعبيرات لامدا Lambda expressions
</h3>

<p>
	لا يكون تعبير لامدا إلا نوع إعادة زائد فقط؛ إذ أنّ صيغة نوع الإعادة البادئ لا يمكن تطبيقها على دوالّ لامدا، لاحظ أنّه من غير الضروري غالبًا تحديد النوع المُعاد لأجل دالة لامدا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_272" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Derived1</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Derived2</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> lambda </span><span class="pun">=[](</span><span class="kwd">bool</span><span class="pln"> b</span><span class="pun">)-&gt;</span><span class="typ">Base</span><span class="pln"> </span><span class="pun">*</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">b</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Derived1</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">else</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Derived2</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// auto lambda = Base*[](bool b) { ... }; صيغة سيئة</span></pre>

<h2>
	محاذاة الأنواع
</h2>

<p>
	جميع الأنواع في C++‎ لها محاذاة (alignment) تمثّل قيودًا على عناوين الذاكرة التي يمكن لكائنات تلك الأنواع أن تُنشأ فيها. ويكون عنوان في الذاكرة صالحًا لإنشاء كائن ما إذا كان العنوان قابلًا للقسمة على محاذاة ذلك الكائن. تساوي محاذاة الأنواع دائمًا قوةً للعدد 2 (بما في ذلك العدد 1، والذي يساوي 2 أسّ 0).
</p>

<h3>
	التحكم في المحاذاة
</h3>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	يمكن استخدام الكلمة المفتاحية <code>‎alignas‎</code> لفرض محاذاة معيّنة على متغيّر أو حقل من صنف، أو تصريح صنف أو تعريفه، أو تصريح تعداد أو تعريفه. وتأتي في شكلين:
</p>

<ul>
<li>
		<code>alignas(x)‎</code> - حيث <code>x</code> تعبير ثابت، يمثّل محاذاة الكيان إن كانت مدعومة.
	</li>
	<li>
		<code>alignas(T)‎</code> - حيث <code>T</code> يمثّل نوعًا، ويجعل محاذاة الكيان مساوية لمحاذاة النوع <code>T</code>، أي <code>alignof(T)‎</code> إذا كانت مدعومة.
	</li>
</ul>
<p>
	ستُطبَّق المحاذاة الأكثر صرامة إذا تم تطبيق عددة محدِّدات على نفس الكيان.
</p>

<p>
	في المثال التالي، نضمن أن يكون للمخزن المؤقّت <code>‎buf‎</code> المحاذاة المناسبة لتخزين كائن <code>‎int‎</code> رغم أنّ نوع عناصره هو <code>‎unsigned char‎</code>، والذي قد تكون محاذاته أضعف.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_274" style="">
<span class="pln">alignas</span><span class="pun">(</span><span class="typ">int</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">unsigned</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> buf</span><span class="pun">[</span><span class="kwd">sizeof</span><span class="pun">(</span><span class="typ">int</span><span class="pun">)];</span><span class="pln">
</span><span class="kwd">new</span><span class="pun">(</span><span class="pln">buf</span><span class="pun">)</span><span class="pln"> </span><span class="typ">int</span><span class="pun">(</span><span class="lit">42</span><span class="pun">);</span></pre>

<p>
	لا يمكن استخدام <code>‎alignas‎</code> لجعل محاذاة نوع معيّن أصغر من المحاذاة الطبيعية التي كان سيحصل عليها بدونها، انظر المثال التالي حيث تُعد صيغة السطر الأول خاطئة إلا إن كانت محاذاة <code>int</code> هي 1 بايت، وكذلك في السطر الثاني تكون خاطئة إلا إن كانت محاذاة <code>int</code> تساوي محاذاة <code>char</code> أو أقل منها.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_276" style="">
<span class="pln">alignas</span><span class="pun">(</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">  
alignas</span><span class="pun">(</span><span class="kwd">char</span><span class="pun">)</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> j</span><span class="pun">;</span><span class="pln">    </span></pre>

<p>
	يجب تمرير محاذاة صالحة لـ <code>‎alignas‎</code> عند إعطائها تعبيرًا ثابتًا صحيحًا، وينبغي للمحاذاة الصالحة أن تساوي دائمًا قوةً للعدد 2، ويجب أن تكون أكبر من الصفر. وتُلزَم المٌصرّفات بدعم جميع قيم المحاذاة الصالحة شرط ألًا تتجاوز محاذاة النوع <code>‎std::max_align_t‎</code>، لكن من الممكن أن تدعم محاذاة أكبر من ذلك، إلا أن دعم تخصيص الذاكرة لمثل هذه الكائنات محدود، كما أنّ الحد الأعلى للمحاذاة يتعلّق بالتنفيذ.
</p>

<p>
	توفّر C++‎ 17 دعمًا مباشرًا في <code>‎operator new‎</code> لتخصيص الذاكرة للأنواع ذات المحاذاة الزائدة (over-aligned types).
</p>

<h3>
	الاستعلام عن محاذاة نوع
</h3>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	يمكن الاستعلام عن محاذاة نوع معيّن باستخدام الكلمة المفتاحية <code>‎alignof‎</code> كمُعامل أحادي، وتكون لنتيجة تعبيرًا ثابتًا من النوع <code>‎std::size_t‎</code>، مما يعني إمكانية تقييمه في وقت التصريف.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_278" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"The alignment requirement of int is: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="kwd">alignof</span><span class="pun">(</span><span class="typ">int</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	خرج محتمل:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4068_280" style="">
<span class="typ">The</span><span class="pln"> alignment requirement of </span><span class="typ">int</span><span class="pln"> is</span><span class="pun">:</span><span class="pln"> </span><span class="lit">4</span></pre>

<p>
	تعيد المحاذاةَ المطلوبة لنوع عناصر في مصفوفة في حال تطبيقها على تلك المصفوفة، أمّا في حال تطبيقها على نوع مرجع (reference type)، فستعيد محاذاة النوع الذي يشير إليه ذلك المرجع، إذ أن المراجع بحد ذاتها ليس لها محاذاة، لأنّها ليست كائنات.
</p>

<p>
	هذا الدرس جزء من <a data-ss1617022768="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصول التالي:
</p>

<ul>
<li>
		Chapter 84: RTTI: Run-Time Type Information
	</li>
	<li>
		Chapter 89: Atomic Types
	</li>
	<li>
		Chapter 90: Type Erasure
	</li>
	<li>
		Chapter 91: Explicit type conversions
	</li>
	<li>
		Chapter 92: Unnamed types
	</li>
	<li>
		Chapter 93: Type Traits
	</li>
	<li>
		Chapter 94: Return Type Covariance
	</li>
	<li>
		Chapter 95: Layout of object types
	</li>
	<li>
		Chapter 96: Type Inference
	</li>
	<li>
		Chapter 97: Typedef and type aliases
	</li>
	<li>
		Chapter 98: type deduction
	</li>
	<li>
		Chapter 99: Trailing return type
	</li>
	<li>
		Chapter 100: Alignment
	</li>
</ul>
<p>
	من كتاب <a data-ss1617022768="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">974</guid><pubDate>Wed, 09 Sep 2020 18:06:00 +0000</pubDate></item><item><title>&#x642;&#x627;&#x639;&#x62F;&#x629; &#x627;&#x644;&#x62B;&#x644;&#x627;&#x62B;&#x629;&#x60C; &#x648;&#x627;&#x644;&#x62E;&#x645;&#x633;&#x629;&#x60C; &#x648;&#x627;&#x644;&#x635;&#x641;&#x631; &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A7%D9%84%D8%AB%D9%84%D8%A7%D8%AB%D8%A9%D8%8C-%D9%88%D8%A7%D9%84%D8%AE%D9%85%D8%B3%D8%A9%D8%8C-%D9%88%D8%A7%D9%84%D8%B5%D9%81%D8%B1-%D9%81%D9%8A-cpp-r973/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_08/44.png.152f68177f6c75edb08f099d42141bfc.png" /></p>

<h2>
	قاعدة الصفر
</h2>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	عند الجمع بين مبادئ "قاعدة الخمسة" (Rule of Five) و <a data-ss1617023040="1" href="https://en.cppreference.com/w/cpp/language/raii" rel="external nofollow"> RAII</a> نحصل على "قاعدة الصفر" (Rule of Zero) ذات الواجهة الرشيقة، والتي قدمها <a data-ss1617023040="1" href="https://isocpp.org/blog/2012/11/rule-of-zero" rel="external nofollow">مارتينيو فرنانديز لأول مرة</a>، وتنصّ على أنّ أيّ مورِدٍ تجب إدارته ينبغي أن يكون في نوعه الخاص. ويجب أن يتبع ذلك النوع "قاعدة الخمسة"، لكن ليس على كلّ مستخدمي ذلك المورد أن يكتبوا التوابع الخمسة التي تتطلّبها "قاعدة الخمسة" (كما سنرى لاحقا)، إذ يمكنهم استخدام الإصدار الافتراضي <code>‎default‎</code> من تلك التوابع. وسننشئ في مثال قاعدة الثلاثة أدناه كائنًا لإدارة موارد <code>cstrings</code> باستخدام الصنف <code>Person</code>، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6088_7" style="">
<span class="kwd">class</span><span class="pln"> cstring </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
</span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> p</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
 </span><span class="pun">~</span><span class="pln">cstring</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">delete</span><span class="pln"> </span><span class="pun">[]</span><span class="pln"> p</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
 cstring</span><span class="pun">(</span><span class="pln">cstring </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
 cstring</span><span class="pun">(</span><span class="pln">cstring</span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
 cstring</span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">=(</span><span class="pln">cstring </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
 cstring</span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">=(</span><span class="pln">cstring</span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">);</span><span class="pln">

    </span><span class="com">/* أعضاء آخرون */</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	يصبح الصنف <code>‎Person‎</code> أكثر بساطة بعد فصل الشيفرة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6088_9" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Person</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    cstring name</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> arg</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="pun">~</span><span class="typ">Person</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">Person</span><span class="pun">(</span><span class="typ">Person</span><span class="pln">
            </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">Person</span><span class="pun">(</span><span class="typ">Person</span><span class="pln"> </span><span class="pun">&amp;&amp;)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">Person</span><span class="pln"> </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pun">=(</span><span class="typ">Person</span><span class="pln">
            </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">Person</span><span class="pln"> </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pun">=(</span><span class="typ">Person</span><span class="pln"> </span><span class="pun">&amp;&amp;)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
    </span><span class="com">/*أعضاء آخرون */</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	لا يلزم التصريح عن الأعضاء الخاصين في <code>‎Person‎</code> صراحة إذ سيتكفّل المُصرّف باعتماد الإصدار الافتراضي أو حذفها استنادًا إلى محتويات <code>‎Person‎</code>. إليك مثالًا آخر عن قاعدة الصفر.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6088_11" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Person</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    cstring name</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> arg</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	إذا كان النوع <code>‎cstring‎</code> للنقل فقط (move-only type)، وكان يحتوي على عامل إنشاء/ إسناد <code>‎deleted‎</code>، فسيكون <code>‎Person‎</code> تلقائيًا للنقل فقط أيضًا.
</p>

<h2>
	قاعدة الخمسة Rule of Five
</h2>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	قدَّمت C++‎ 11 دالتين تابعتين جديدتين هما مُنشئ النقل (move constructor) وعامل إسناد النقل (operator move assignment)، وستجد أن نفس الأسباب التي قد تجعلك ترغب في اتّباع "قاعدة الثلاثة" في C++‎ 03 (انظر أدناه) ستجعلك تتّبع أيضًا "قاعدة الخمسة" في C++‎ 11: أنه إذا كان الصنف يتطلّب إحدى الدوال التابعة الخاصّة وكانت دلالات النقل (move semantics) مطلوبة، فالراجح أن الصنف سيتطّلب كلّ التوابع الخمسة، لكن اعلم أنّ عدم اتباع "قاعدة الخمسة" لا يُعدُّ خطأ عادةً طالما أنّك تتّبع قاعدة الثلاثة، لكنّه قد يضيّع عليك فرصة تحسين برنامجك.
</p>

<p>
	إذا لم يكن مُنشئ نقل أو مُعامل إسناد النقل متاحًا عندما يحتاجه المصرّف فسيَستخدم دلالات النسخ إن أمكن، هذا قد يؤدّي إلى إضعاف الكفاءة بسبب إجراء عمليات نسخ غير ضرورية. كذلك، لن تحتاج إلى التصريح عن مُنشئ نقل أو مُعامل إسناد إذا لم يكن الصنف بحاجة إلى دلالات النقل. انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6088_13" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Person</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">*</span><span class="pln">name</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> age</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="com">// مدمّر</span><span class="pln">
        </span><span class="pun">~</span><span class="typ">Person</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">delete</span><span class="pun">[]</span><span class="pln"> name</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// نفِّذ دلالات النَّسخ</span><span class="pln">
    </span><span class="typ">Person</span><span class="pun">(</span><span class="typ">Person</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">other</span><span class="pun">):</span><span class="pln"> name</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">[</span><span class="pln">std</span><span class="pun">::</span><span class="pln">strlen</span><span class="pun">(</span><span class="pln">other</span><span class="pun">.</span><span class="pln">name</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">]),</span><span class="pln"> age</span><span class="pun">(</span><span class="pln">other</span><span class="pun">.</span><span class="pln">age</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">strcpy</span><span class="pun">(</span><span class="pln">name</span><span class="pun">,</span><span class="pln"> other</span><span class="pun">.</span><span class="pln">name</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="typ">Person</span><span class="pln"> </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pun">=(</span><span class="typ">Person</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">other</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// استخدام أسلوب النسخ والمبادلة لتقديم عملية الإسناد</span><span class="pln">
        </span><span class="typ">Person</span><span class="pln"> copy</span><span class="pun">(</span><span class="pln">other</span><span class="pun">);</span><span class="pln">
        swap</span><span class="pun">(*</span><span class="kwd">this</span><span class="pun">,</span><span class="pln"> copy</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="com">// نفذ دلالات النقل.</span></pre>

<p>
	اعلم أن الأفضل هو جعل عوامل النقل كـ <code>noexcept</code>، إذ يسمح ذلك بتنفيذ بعض التحسينات من قبل المكتبة القياسية عند استخدام الصنف داخل حاوية، نتابع المثال …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6088_15" style="">
<span class="pln">       </span><span class="typ">Person</span><span class="pun">(</span><span class="typ">Person</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> that</span><span class="pun">)</span><span class="pln"> noexcept</span><span class="pun">:</span><span class="pln"> name</span><span class="pun">(</span><span class="kwd">nullptr</span><span class="pun">)</span><span class="pln"> </span><span class="com">// ضبط القيمة لنعلم أنها غير محددة</span><span class="pln">
    </span><span class="pun">,</span><span class="pln"> age</span><span class="pun">(</span><span class="lit">0</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            swap</span><span class="pun">(*</span><span class="kwd">this</span><span class="pun">,</span><span class="pln"> that</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

    </span><span class="typ">Person</span><span class="pln"> </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pun">=(</span><span class="typ">Person</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> that</span><span class="pun">)</span><span class="pln"> noexcept
    </span><span class="pun">{</span><span class="pln">
        swap</span><span class="pun">(*</span><span class="kwd">this</span><span class="pun">,</span><span class="pln"> that</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">friend</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> swap</span><span class="pun">(</span><span class="typ">Person</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">lhs</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Person</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">rhs</span><span class="pun">)</span><span class="pln"> noexcept
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">swap</span><span class="pun">(</span><span class="pln">lhs</span><span class="pun">.</span><span class="pln">name</span><span class="pun">,</span><span class="pln"> rhs</span><span class="pun">.</span><span class="pln">name</span><span class="pun">);</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">swap</span><span class="pun">(</span><span class="pln">lhs</span><span class="pun">.</span><span class="pln">age</span><span class="pun">,</span><span class="pln"> rhs</span><span class="pun">.</span><span class="pln">age</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	تستطيع -كخيار آخر- استبدال كل من مُعامل إسناد النسخ والنقل بمُعامل إسناد واحد يأخذ نسخة بالقيمة (by value) بدلاً من أخذها بالمرجع أو <a data-ss1617023040="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-40-%D9%81%D8%A6%D8%A7%D8%AA-%D8%A7%D9%84%D9%82%D9%8A%D9%85-value-categories-%D9%81%D9%8A-cpp-r969/" rel="">بالمرجع اليميني</a> (rvalue reference)، وذلك لتسهيل استخدام تقنيات النسخ والمبادلة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6088_17" style="">
<span class="typ">Person</span><span class="pln"> </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pun">=(</span><span class="typ">Person</span><span class="pln"> copy</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    swap</span><span class="pun">(*</span><span class="kwd">this</span><span class="pun">,</span><span class="pln"> copy</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	واعلم أن التوسّع من "قاعدة الثلاثة" إلى "قاعدة الخمسة" مهمّ لأسباب تتعلق بالأداء لكنّه في أغلب الحالات غير ضروري، ويضمن إضافة مُنشئ النسخ ومُعامل الإسناد أنّ نقل النوع لن يؤدّي إلى تسرّب الذاكرة -سيتحوّل إنشاء النقل إلى النسخ في هذه الحالة- لكنّه سيجري عمليات نسخ لم يتوقعها المُستدعي على الأرجح.
</p>

<h2>
	قاعدة الثلاثة Rule of Three
</h2>

<p>
	<strong>الإصدار ≤ C++‎ 03</strong>
</p>

<p>
	تنصّ قاعدة الثلاثة على أنّه إن احتاج نوع معيّن أن يكون له مُنشئ نسخ مُعرَّف من قبل المستخدم (user-defined copy constructor)، أو مُعامل إسناد نسخ أو مُدمِّر، فيجب أن يتحوي على الثلاثة معًا.
</p>

<p>
	وسبب إنشاء هذه القاعدة هو أنّ الصنف الذي يحتاج أيًّا من تلك الوظائف الثلاثة سيحتاج أيضًا إلى إدارة الموارد (مقابض الملفات، الذاكرة المخصّصة ديناميكيًا، الخ)، لكن إدارة تلك المورد تحتاج دائمًا إلى تلك الوظائف الثلاث، وتتكفّل دوال النسخ بنسخ الموارد من كائن لآخر بينما يتكفّل المدمّر بتدمير المورد وفقًا لمبادئ <a data-ss1617023040="1" href="https://en.cppreference.com/w/cpp/language/raii" rel="external nofollow">RAII</a>.
</p>

<p>
	يقدّم المثال التالي نوعًا يدير السلاسل النصية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6088_19" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Person</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">*</span><span class="pln">name</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> age</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Person</span><span class="pun">(</span><span class="kwd">char</span><span class="pln">
            </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">*</span><span class="pln">new_name</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> new_age</span><span class="pun">):</span><span class="pln"> name</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">[</span><span class="pln">std</span><span class="pun">::</span><span class="pln">strlen</span><span class="pun">(</span><span class="pln">new_name</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">]),</span><span class="pln"> age</span><span class="pun">(</span><span class="pln">new_age</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">strcpy</span><span class="pun">(</span><span class="pln">name</span><span class="pun">,</span><span class="pln"> new_name</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}~</span><span class="typ">Person</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">delete</span><span class="pun">[]</span><span class="pln"> name</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	وبما أن ذاكرة <code>‎name‎</code> مُخصّصة في المنشئ، فسيُلغي المدمّر تخصيصها لتجنّب تسرّب الذاكرة. لكن ماذا سيحدث في حال نُسِخ الكائن؟
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6088_21" style="">
<span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Person</span><span class="pln"> p1</span><span class="pun">(</span><span class="str">"foo"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">11</span><span class="pun">);</span><span class="pln">
    </span><span class="typ">Person</span><span class="pln"> p2 </span><span class="pun">=</span><span class="pln"> p1</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	أولاً، سيُنشَأ <code>‎p1‎</code>، ثم يُنسَخ <code>‎p2‎</code> من <code>‎p1‎</code>. لكن مُنشئ النسخ المُولَّد من C++‎ سينسخ كل مكوّن من مكوّنات النوع كما هو، ممّا يعني أنّ كلًّا من <code>‎p1.name‎</code> و <code>‎p2.name‎</code> سيشيران إلى نفس السلسلة النصّية.
</p>

<p>
	وعند انتهاء <code>‎main‎</code> ستُستدعى المدمّرات ابتداءً بمدمّر <code>‎p2‎</code> الذي سيحذف السلسلة النصّية. ثم سيُستدعى مدمّر <code>‎p1‎</code>. لكنّ السلسلة النصية قد حُذِفت سلفًا. سينتج سلوك غير محدد عند استدعاء <code>‎delete‎</code> على ذاكرة حُذِفت فعلًا، ويجب توفير مُنشئ نسخ مناسب لتجنّب هذا.
</p>

<p>
	وإحدى طرق ذلك هي تطبيق نظام عدٍّ للمراجع (reference counted system)، حيث تتشارك مختلف نُسخ <code>‎Person‎</code> نفس البيانات النصية، ويُزاد عدّاد المرجع المشترك عند كلّ عملية نسخ، ثم يُنقِص المدمّر بعدها عدّاد المرجع، ولا يُحرِّر الذاكرة إلّا إذا كان العدّاد يساوي الصفر.
</p>

<p>
	يمكننا أيضًا تطبيق الدلالات القيمية (value semantics) وسلوك النسخ العميق (deep copying):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6088_23" style="">
<span class="typ">Person</span><span class="pun">(</span><span class="typ">Person</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">other</span><span class="pun">):</span><span class="pln"> name</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">[</span><span class="pln">std</span><span class="pun">::</span><span class="pln">strlen</span><span class="pun">(</span><span class="pln">other</span><span class="pun">.</span><span class="pln">name</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">]),</span><span class="pln"> age</span><span class="pun">(</span><span class="pln">other</span><span class="pun">.</span><span class="pln">age</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">strcpy</span><span class="pun">(</span><span class="pln">name</span><span class="pun">,</span><span class="pln"> other</span><span class="pun">.</span><span class="pln">name</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">Person</span><span class="pln"> </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pun">=(</span><span class="typ">Person</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">other</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// استخدام أسلوب النسخ والمبادلة لتطبيق معامل الإسناد</span><span class="pln">
    </span><span class="typ">Person</span><span class="pln"> copy</span><span class="pun">(</span><span class="pln">other</span><span class="pun">);</span><span class="pln">
    swap</span><span class="pun">(</span><span class="pln">copy</span><span class="pun">);</span><span class="pln">    </span><span class="com">// *this و copy تُبادِلُ محتويات swap() افتراض أن</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تطبيق مُعامل إسناد النسخ معقّد بسبب الحاجة إلى تحرير مخزن مؤقّت (buﬀer)، وتنشئ تقنية النسخ والمبادلة كائنًا مؤقّتًا يحتفظ بالمخزن المؤقّت، ثم يمنح تبديل محتويات <code>‎*this‎</code> و <code>‎copy‎</code> مِلكِية المخزن المؤقّت لـ <code>‎copy‎</code>، وعند تدمير <code>‎copy‎</code> -عند عودة الدالّة- فسيُحرَّر المخزن المؤقّت الذي يملكه <code>‎*this‎</code>.
</p>

<h2>
	الوقاية من الإسناد الذاتي
</h2>

<p>
	عندما تكتب عامل إسناد نسخٍ فيجب أن تدرك أنه يجب أن يظل عاملًا في حالة حدوث إسناد ذاتي، أي يجب أن يسمح بما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6088_25" style="">
<span class="typ">SomeType</span><span class="pln"> t </span><span class="pun">=</span><span class="pln"> </span><span class="pun">...;</span><span class="pln">
t </span><span class="pun">=</span><span class="pln"> t</span><span class="pun">;</span></pre>

<p>
	لا يحدث الإسناد الذاتي عادة بهذه الطريقة، وإنما يحدث في مسار دائري (circuitous route) في أنظمة الشيفرات، إذ يكون لموضع الإسناد (location of the assignment) مؤشّران أو مرجعان يشيران إلى كائن من النوع <code>‎Person‎</code>، دون أن يدركا أنّهما في الحقيقة يمثّلان نفس الكائن.
</p>

<p>
	ويجب أن يُصمَّم أي عامل إسناد نسخ تكتبه للتعامل مع هذا الأمر، والطريقة المعتادة لفعل ذلك هي بتغليف كامل منطق الإسناد في عبارة شرطية على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6088_27" style="">
<span class="typ">SomeType</span><span class="pln"> </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pun">=(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">SomeType</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">other</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">this</span><span class="pln"> </span><span class="pun">!=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">other</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// منطق الإسناد هنا</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>ملاحظة</strong>: من المهم أخذ الإسناد الذاتي في الحسبان، والحرص على أنّ شيفرتك ستتصرّف بالشكل الصحيح عند حدوثه. وبما أن الإسناد الذاتي أمر نادر الحدوث، وقد يؤدّي تحسين الشيفرة خصّيصًا لمنعه إلى التشويش على الحالة الطبيعية، فقد يؤدّي ذلك إلى تقليل كفاءة الشيفرة لأنّ الحالة العادية أكثر شيوعًا (لذا كن حذرًا عند استخدامه).
</p>

<p>
	على سبيل المثال، الأسلوب العادي لتقديم مُعامل الإسناد هو أسلوب النسخ والمبادلة ، لكن التطبيق العادي لهذه التقنية لا يكلف نفسه عناء التحقق من الإسناد الذاتي -رغم أنّ الإسناد الذاتي مكلّف لأنّه ينطوي على عمليّة نسخ- والسبب هو أن الاحتياط أثبت أنه أكثر كلفة بكثير من الإسناد الذاتي بما أنه يحدث بكثرة.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	كذلك يجب وقاية مُعاملات إسناد النقل من الإسناد الذاتي، لكن يبنى منطق عديد من هذه العوامل على <code>‎std::swap‎</code>، والتي تستطيع التعامل مع التبديل من/إلى نفس الذاكرة بلا مشاكل. لذا إذا كان منطق إسناد النقل الخاص بك يتألّف حصرًا من سلسلة من عمليات التبديل فلن تحتاج إلى الاحتياط من الإسناد الذاتي. أما خلاف هذا فيجب عليك اتخاذ تدابير مماثلة على النحو الوارد أعلاه.
</p>

<p>
	هذا الدرس جزء من <a data-ss1617023040="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 82: The Rule of Three, Five, And Zero من كتاب <a data-ss1617023040="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">973</guid><pubDate>Mon, 07 Sep 2020 18:00:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62E;&#x64A;&#x648;&#x637; Threading &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AE%D9%8A%D9%88%D8%B7-threading-%D9%81%D9%8A-cpp-r972/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_08/43.png.9e45a7ef79335faa846de6d637bfa743.png" /></p>

<h2>
	كيفية إنشاء خيط std::thread
</h2>

<p>
	تُنشَأ الخيوط في C++‎ باستخدام الصنف <code>std::thread</code>، والخيط (thread) هو مسار تنفيذ منفصل أشبه بمساعد يساعدك على أداء مهمة فرعية أثناء إنجازك لمهمة أخرى، ثم يتوقف عند اكتمال تنفيذ الشيفرة في الخيط.
</p>

<p>
	يجب أن تمرر شيفرة ما للخيط عند إنشائه لينفذها، مثل:
</p>

<ul>
<li>
		الدوالّ الحرّة (Free functions).
	</li>
	<li>
		الدوال التابعة.
	</li>
	<li>
		الكائنات الدالية (Functor).
	</li>
	<li>
		<a data-ss1615541024="1" data-ss1615541531="1" data-ss1617023041="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-39-%D8%AF%D9%88%D8%A7%D9%84-%D9%84%D8%A7%D9%85%D8%AF%D8%A7-lambdas-%D9%81%D9%8A-cpp-r960/" rel="">تعبيرات لامدا</a>.
	</li>
</ul>
<p>
	تكون المعاملات المُمرَّرة:
</p>

<table>
<thead><tr>
<th>
				المعامل
			</th>
			<th>
				التفاصيل
			</th>
		</tr></thead>
<tbody>
<tr>
<td>
				<code>other</code>
			</td>
			<td>
				تأخذ ملكية <code>‎other‎</code>، بحيث أنّ <code>‎other‎</code> تفقد ملكيّة <a data-ss1615541024="1" data-ss1615541531="1" data-ss1617023041="1" href="%D8%B1%D8%A7%D8%A8%D8%B7%20%D8%A7%D9%84%D9%81%D8%B5%D9%84%2080" rel="">الخيط</a> (thread)
			</td>
		</tr>
<tr>
<td>
				<code>func</code>
			</td>
			<td>
				دالّة لأجل استدعائها في خيط منفصل
			</td>
		</tr>
<tr>
<td>
				<code>args</code>
			</td>
			<td>
				وسائط لـ <code>‎func‎</code>
			</td>
		</tr>
</tbody>
</table>
<style type="text/css">
table {
    width: 100%;
}

thead {
    vertical-align: middle;
    text-align: center;
}

td, th {
    border: 1px solid #dddddd;
    text-align: right;
    padding: 8px;
    text-align: inherit;

}
tr:nth-child(even) {
    background-color: #dddddd;
}</style>
<p>
	<a data-ss1615541024="1" data-ss1615541531="1" data-ss1617023041="1" href="https://ideone.com/hX1Ygn" rel="external nofollow">هذا مثال على تمرير دالّة حرّة لتُنفّذ في خيط منفصل</a>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_7" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;thread&gt;</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> a </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// إنشاء وتنفيذ الخيط</span></pre>

<p>
	تكون <code>foo</code> هنا هي الدالة محل التنفيذ، و10 هو الوسيط الممرر إليها، وسينفَذ الخيط الآن بشكل منفصل ويُنتَظر هنا حتى تمام تنفيذه، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_9" style="">
<span class="pln">    std</span><span class="pun">::</span><span class="pln">thread thread</span><span class="pun">(</span><span class="pln">foo</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">);</span><span class="pln">    

    thread</span><span class="pun">.</span><span class="pln">join</span><span class="pun">();</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<a data-ss1615541024="1" data-ss1615541531="1" data-ss1617023041="1" href="https://ideone.com/4QeG4E" rel="external nofollow">هذا مثال على استخدام تابع ليُنفّذ في خيط منفصل</a>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_11" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;thread&gt;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Bar</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> a </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Bar</span><span class="pln"> bar</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// إنشاء وتنفيذ الخيط</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">thread thread</span><span class="pun">(&amp;</span><span class="typ">Bar</span><span class="pun">::</span><span class="pln">foo</span><span class="pun">,</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">bar</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">);</span><span class="pln">    </span><span class="com">// Pass 10 to member function</span></pre>

<p>
	التابع سيُنفَّذ الآن بشكل منفصل، سننتظر هنا حتى تمام تنفيذ الخيط، فهذه عملية معطِّلة (Blocking)، نتابع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_15" style="">
<span class="pln">    thread</span><span class="pun">.</span><span class="pln">join</span><span class="pun">();</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<a data-ss1615541024="1" data-ss1615541531="1" data-ss1617023041="1" href="https://ideone.com/h2EepE" rel="external nofollow">مثال على استخدام كائن دالّي</a>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_17" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;thread&gt;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Bar</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">()(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> a </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Bar</span><span class="pln"> bar</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// انشاء الخيط وتنفيذه</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">thread thread</span><span class="pun">(</span><span class="pln">bar</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">);</span><span class="pln">    </span><span class="com">// مرر 10 إلى الكائن الدالي.</span></pre>

<p>
	سيُنفَّذ الكائن الدالي الآن بشكل منفصل، سننتظر هنا حتى تمام تنفيذ الخيط، فهذه عملية معطِّلة (Blocking)، نتابع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_19" style="">
<span class="pln">   thread</span><span class="pun">.</span><span class="pln">join</span><span class="pun">();</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<a data-ss1615541024="1" data-ss1615541531="1" data-ss1617023041="1" href="https://ideone.com/UacLRf" rel="external nofollow">مثال على تمرير تعبير لامدا</a>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_22" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;thread&gt;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> lambda </span><span class="pun">=[](</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> a </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
    </span><span class="com">// انشاء الخيط وتنفيذه</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">thread thread</span><span class="pun">(</span><span class="pln">lambda</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">);</span><span class="pln">    </span><span class="com">// تمرير 10 إلى تعبير لامدا</span></pre>

<p>
	سيُنفَّذ تعبير لامدا الآن بشكل منفصل، وسننتظر اكتمال تنفيذ الخيط، فهي عملية معطِّلة، نتابع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_24" style="">
<span class="pln">    thread</span><span class="pun">.</span><span class="pln">join</span><span class="pun">();</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	تمرير مرجع إلى خيط
</h2>

<p>
	لا يمكنك تمرير مرجع -أو مرجع ثابت <code>‎const‎</code>- مباشرةً إلى خيط، لأنّ الخيط سينسخها/ينقلها، بل استخدم <code>‎std::reference_wrapper‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_26" style="">
<span class="kwd">void</span><span class="pln"> foo</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> b</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">thread thread
</span><span class="pun">{</span><span class="pln">
    foo</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">ref</span><span class="pun">(</span><span class="pln">a</span><span class="pun">)</span><span class="pln">
</span><span class="pun">};</span><span class="pln">    </span></pre>

<p>
	الآن، <code>a</code> ممرَّرة على شكل مرجع، تابع المثال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_28" style="">
<span class="pln">thread</span><span class="pun">.</span><span class="pln">join</span><span class="pun">();</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> a </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">    </span><span class="com">//  10</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> bar</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">ComplexObject</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">co</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    co</span><span class="pun">.</span><span class="pln">doCalculations</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">ComplexObject</span><span class="pln"> object</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">thread thread
</span><span class="pun">{</span><span class="pln">
    bar</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">cref</span><span class="pun">(</span><span class="pln">object</span><span class="pun">)</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	أيضًا، <code>object</code> ممرَّر الآن على شكل <code>&amp;const</code>، تابع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_30" style="">
<span class="pln">thread</span><span class="pun">.</span><span class="pln">join</span><span class="pun">();</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> object</span><span class="pun">.</span><span class="pln">getResult</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">   </span></pre>

<h2>
	استخدام std::async بدلاً من std::thread
</h2>

<p>
	تستطيع <code>‎</code>std‎::async أن تنشئ خيوطًا رغم أنها أضعف من <code>‎std‎</code>::thread، لكنّها تتميّر بأنّها أسهل في حال كنت تريد تنفيذ دالة بشكل غير متزامن (asynchronously).
</p>

<h3>
	استدعاء دالّة بشكل غير متزامن
</h3>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_32" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;future&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="kwd">unsigned</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> square</span><span class="pun">(</span><span class="kwd">unsigned</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> i </span><span class="pun">*</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> f </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">async </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">launch</span><span class="pun">::</span><span class="pln">async</span><span class="pun">,</span><span class="pln"> square</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"square currently running\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// square افعل شيئا ما أثناء تنفيذ</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"result is "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> f</span><span class="pun">.</span><span class="pln">get</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">    </span><span class="com">// square الحصول على النتيجة من</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	أخطاء شائعة
</h3>

<ul>
<li>
		تعيد <code>std::async</code> كائن <code>std::future</code> يحتوي القيمة المُعادة التي ستحسُبها الدالّة، وعند تدمير <code>‎future‎</code> فإنّها تنتظر حتى يكتمل الخيط ممّا يجعل الشيفرة أحادية الخيوط (single threaded). يُمكن تجاهَل هذا السلوك إذا لم تكن بحاجة إلى القيمة المُعادة:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_34" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">async </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">launch</span><span class="pun">::</span><span class="pln">async</span><span class="pun">,</span><span class="pln"> square</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">);</span></pre>

<p>
	في الشيفرة السابقة، انتهى تنفيذ الخيط لأن قيمة <code>future</code> قد دُمِّرت.
</p>

<ul>
<li>
		تعمل <code>std::async</code> بدون سياسة إطلاق (launch policy)، لذا فإنّ التعبير <code>‎std::async(square, 5);‎</code> سيُصرَّف. عندئذ يقرر النظام إن كان سينشئ خيطًا أم لا. والفكرة أنّ النظام سيختار إنشاء خيط إن لم يكن عدد الخيوط قيد التنفيذ أكبر ممّا يمكنه التعامل معه. لكن عادة ما تختار التنفيذات (implementations) عدم إنشاء خيط في مثل هذه المواقف، لذا ستحتاج إلى إعادة تعريف هذا السلوك باستخدام <code>‎std::launch::async‎</code>، التي تجبر النظام على إنشاء الخيط.
	</li>
</ul>
<h2>
	أساسيات التزامن بين الخيوط
</h2>

<p>
	يمكن تحقيق تزامن الخيوط باستخدام كائنات المزامنة (mutexes)، وتوفّر المكتبة القياسية العديد من أنواع كائنات المزامنة تلك لكن أبسطها هو <code>‎std::mutex‎</code> وسنتحدث عن تلك الكائنات بالتفصيل في القسم التالي.
</p>

<p>
	ولقفل كائن مزامنة ستحتاج إلى إنشاء قفل (lock) خاصّ به، وأبسط أنواع الأقفال هو <code>‎std::lock_guard‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_36" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">mutex m</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> worker</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">lock_guard</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">mutex </span><span class="pun">&gt;</span><span class="pln"> guard</span><span class="pun">(</span><span class="pln">m</span><span class="pun">);</span><span class="pln">    </span><span class="com">// يحصل على قفلٍ على كائن المزامنة</span><span class="pln">
    </span><span class="com">// الشيفرة المُزامَنة هنا</span><span class="pln">
</span><span class="pun">}</span><span class="pln">    </span><span class="com">// سيُحرَّر كائن المزامنة عندما يخرج الدرع عن النطاق </span></pre>

<p>
	سيُقفل كائن المزامنة باستخدام <code>‎std::lock_guard‎</code> طول العمر الافتراضي لكائن القفل، وإن أردت التحكم في المناطق المقفلة يدويًا، فاستخدم <code>‎std::unique_lock‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_38" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">mutex m</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> worker</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span></pre>

<p>
	افتراضيًا، إنشاء <code>unique_lock</code> من كائن مزامنة سيقفل ذلك الكائن، ونستطيع إنشاء درع في حالة مفتوحة عبر تمرير <code>std::defer_lock</code> كوسيط ثاني ثم نقفل يدويًا فيما بعد، تابع المثال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_40" style="">
<span class="pln">    std</span><span class="pun">::</span><span class="pln">unique_lock</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">mutex </span><span class="pun">&gt;</span><span class="pln"> guard</span><span class="pun">(</span><span class="pln">m</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">defer_lock</span><span class="pun">);</span><span class="pln">
    </span><span class="com">// لم يُقفَل كائن المزامنة بعد</span><span class="pln">
    guard</span><span class="pun">.</span><span class="pln">lock</span><span class="pun">();</span><span class="pln">
    </span><span class="com">// شيفرة خاصة</span><span class="pln">
    guard</span><span class="pun">.</span><span class="pln">unlock</span><span class="pun">();</span><span class="pln">
    </span><span class="com">// تحرير كائن المزامنة مجددا</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	كائنات المزامنة Mutexes
</h3>

<p>
	كائنات المزامنة هي بنيات مزامنة بسيطة غير تكرارية (non-recursive) تُستخدَم لحماية البيانات التي يمكن الوصول إليها من خيوط متعددة (multiple threads).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_42" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">atomic_int temp
</span><span class="pun">{</span><span class="pln">
    </span><span class="lit">0</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">mutex _mutex</span><span class="pun">;</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">thread t</span><span class="pun">([</span><span class="pln"> </span><span class="pun">&amp;]()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">temp </span><span class="pun">!=</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">this_thread</span><span class="pun">::</span><span class="pln">sleep_for</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">chrono</span><span class="pun">::</span><span class="pln">seconds</span><span class="pun">(</span><span class="lit">5</span><span class="pun">));</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">unique_lock</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">mutex </span><span class="pun">&gt;</span><span class="pln"> lock</span><span class="pun">(</span><span class="pln">_mutex</span><span class="pun">);</span><span class="pln">

        temp </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> </span><span class="pun">});</span><span class="pln">

</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">this_thread</span><span class="pun">::</span><span class="pln">sleep_for</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">chrono</span><span class="pun">::</span><span class="pln">milliseconds</span><span class="pun">(</span><span class="lit">1</span><span class="pun">));</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">unique_lock</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">mutex </span><span class="pun">&gt;</span><span class="pln"> lock</span><span class="pun">(</span><span class="pln">_mutex</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">try_to_lock</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">temp </span><span class="pun">&lt;</span><span class="pln"> INT_MAX</span><span class="pun">)</span><span class="pln">
        temp</span><span class="pun">++;</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> temp </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">

</span><span class="pun">}</span></pre>

<h4>
	أنواع كائنات المزامنة
</h4>

<p>
	توفّر الإصدارات C++1x عددًا من أصناف كائنات المزامنة:
</p>

<ul>
<li>
		<code>std::mutex</code> - توفّر وظائف القفل الأساسية.
	</li>
	<li>
		<code>std::timed_mutex</code> - توفّر وظائف <code>try_to_lock</code>
	</li>
	<li>
		<code>std::recursive_mutex</code> - تتيح القفل التكراري من قِبل نفس الخيط
	</li>
	<li>
		<code>std::shared_mutex</code> و <code>std::shared_timed_mutex</code> - توفّران وظائف قفل مشتركة وحصرية
	</li>
</ul>
<h4>
	الأقفال std::lock
</h4>

<p>
	تستخدِم الأقفال <code>std::lock</code> خوارزميات لتجنب الشلل الوظيفي (deadlock) من أجل قفل كائنات المزامنة. وعند رفع اعتراض أثناء استدعاء لقَفل عدة كائنات فستفتح <code>‎std::lock‎</code> الكائنات المُقفلة قبل إعادة رفع الاعتراض.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_44" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">lock</span><span class="pun">(</span><span class="pln">_mutex1</span><span class="pun">,</span><span class="pln"> _mutex2</span><span class="pun">);</span></pre>

<h4>
	الأقفال الحصرية (std::unique_lock) والأقفال المشتركة (std::shared_lock) والأقفال المُؤمّنة ( std::lock_guard)
</h4>

<p>
	تُستخدم هذه الأقفال مع آلية RAII للحصول على أقفال المحاولة (try locks)، وأقفال المحاولة الموقوتة (timed try locks)، والأقفال التكرارية (recursive locks).
</p>

<ul>
<li>
		<code>std::unique_lock</code> - تسمح بالملكية الحصرية لكائنات المزامنة.
	</li>
	<li>
		<code>std::shared_lock</code> - تسمح بالملكية المشتركة لكائنات المزامنة، إذ يمكن لعدّة خيوط أن تحتفظ بقفل مشترك<code>td::shared_locks</code> خاصّ بكائن مزامنة مشترك <code>std::shared_mutex</code>. وقد أتيح منذ C++‎ 14
	</li>
	<li>
		<code>std::lock_guard</code> - بديل خفيف للأقفال الحصرية <code>std::unique_lock</code> والأقفال المشتركة <code>std::shared_lock</code>.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_46" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;unordered_map&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;mutex&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;shared_mutex&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;thread&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;string&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">PhoneBook</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">string getPhoneNo</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&amp;</span><span class="pln">name</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">shared_lock</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">shared_timed_mutex </span><span class="pun">&gt;</span><span class="pln"> l</span><span class="pun">(</span><span class="pln">_protect</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">auto</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> _phonebook</span><span class="pun">.</span><span class="pln">find</span><span class="pun">(</span><span class="pln">name</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">it </span><span class="pun">!=</span><span class="pln"> _phonebook</span><span class="pun">.</span><span class="pln">end</span><span class="pun">())</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(*</span><span class="pln">it</span><span class="pun">).</span><span class="pln">second</span><span class="pun">;</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="str">""</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">void</span><span class="pln"> addPhoneNo</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&amp;</span><span class="pln">name</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&amp;</span><span class="pln">phone</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">unique_lock</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">shared_timed_mutex </span><span class="pun">&gt;</span><span class="pln"> l</span><span class="pun">(</span><span class="pln">_protect</span><span class="pun">);</span><span class="pln">
        _phonebook</span><span class="pun">[</span><span class="pln">name</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> phone</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    std</span><span class="pun">::</span><span class="pln">shared_timed_mutex _protect</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">unordered_map</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&gt;</span><span class="pln"> _phonebook</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<h4>
	استراتيجيات قفل الأصناف: std::try_to_lock و std::adopt_lock و std::defer_lock
</h4>

<p>
	لدينا ثلاث استراتيجيات لتختار منها عند إنشاء قفل حصري: <code>‎std::try_to_lock‎</code> و <code>std::defer_lock</code> و <code>std::adopt_lock</code>:
</p>

<ol>
<li>
		<code>std::try_to_lock</code> - تسمح بمحاولة القفل (trying a lock) بدون تعطيل:
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_48" style="">
<span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">atomic_int temp
    </span><span class="pun">{</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">mutex _mutex</span><span class="pun">;</span><span class="pln">

    std</span><span class="pun">::</span><span class="pln">thread t</span><span class="pun">([</span><span class="pln"> </span><span class="pun">&amp;]()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">temp </span><span class="pun">!=</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">this_thread</span><span class="pun">::</span><span class="pln">sleep_for</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">chrono</span><span class="pun">::</span><span class="pln">seconds</span><span class="pun">(</span><span class="lit">5</span><span class="pun">));</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">unique_lock</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">mutex </span><span class="pun">&gt;</span><span class="pln"> lock</span><span class="pun">(</span><span class="pln">_mutex</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">try_to_lock</span><span class="pun">);</span><span class="pln">

            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">lock</span><span class="pun">.</span><span class="pln">owns_lock</span><span class="pun">())</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="com">//افعل شيئًا</span><span class="pln">
                temp </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln"> </span><span class="pun">});</span><span class="pln">

    </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">this_thread</span><span class="pun">::</span><span class="pln">sleep_for</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">chrono</span><span class="pun">::</span><span class="pln">seconds</span><span class="pun">(</span><span class="lit">1</span><span class="pun">));</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">unique_lock</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">mutex </span><span class="pun">&gt;</span><span class="pln"> lock</span><span class="pun">(</span><span class="pln">_mutex</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">try_to_lock</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">lock</span><span class="pun">.</span><span class="pln">owns_lock</span><span class="pun">())</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">temp </span><span class="pun">&lt;</span><span class="pln"> INT_MAX</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="pun">++</span><span class="pln">temp</span><span class="pun">;</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">

            std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> temp </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<ol start="2">
<li>
		<code>std::defer_lock</code> - تسمح بإنشاء بنية قفل دون الحصول على القفل. ذلك أنه عند قفل أكثر من كائن مزامنة، فهناك إمكانية لحدوث شلل وظيفي إذا حاولت دالتان الحصول على الأقفال في نفس الوقت:
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_50" style="">
<span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">unique_lock</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">mutex </span><span class="pun">&gt;</span><span class="pln"> lock1</span><span class="pun">(</span><span class="pln">_mutex1</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">defer_lock</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">unique_lock</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">mutex </span><span class="pun">&gt;</span><span class="pln"> lock2</span><span class="pun">(</span><span class="pln">_mutex2</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">defer_lock</span><span class="pun">);</span><span class="pln">
    lock1</span><span class="pun">.</span><span class="pln">lock</span><span class="pun">()</span><span class="pln">
    lock2</span><span class="pun">.</span><span class="pln">lock</span><span class="pun">();</span><span class="pln">    </span><span class="com">// شلل وظيفي هنا</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"</span><span class="typ">Locked</span><span class="pun">!</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="com">//...</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكن الحصول على الأقفال وإصدارها بالترتيب المناسب مع الشيفرة التالية، بغض النظر عما يحدث في الدالة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_52" style="">
<span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">unique_lock</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">mutex </span><span class="pun">&gt;</span><span class="pln"> lock1</span><span class="pun">(</span><span class="pln">_mutex1</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">defer_lock</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">unique_lock</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">mutex </span><span class="pun">&gt;</span><span class="pln"> lock2</span><span class="pun">(</span><span class="pln">_mutex2</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">defer_lock</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">lock</span><span class="pun">(</span><span class="pln">lock1</span><span class="pun">,</span><span class="pln"> lock2</span><span class="pun">);</span><span class="pln">    </span><span class="com">// لن يحدث شلل وظيفي.</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"</span><span class="typ">Locked</span><span class="pun">!</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="com">//...</span><span class="pln">

</span><span class="pun">}</span></pre>

<ol start="3">
<li>
		<code>std::adopt_lock</code> - لا تحاول القفل مرّة ثانية إذا كان الخيط المُستدعي يملك القفل حاليًا.
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_54" style="">
<span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">unique_lock</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">mutex </span><span class="pun">&gt;</span><span class="pln"> lock1</span><span class="pun">(</span><span class="pln">_mutex1</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">adopt_lock</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">unique_lock</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">mutex </span><span class="pun">&gt;</span><span class="pln"> lock2</span><span class="pun">(</span><span class="pln">_mutex2</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">adopt_lock</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"</span><span class="typ">Locked</span><span class="pun">!</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="com">//...</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تذكّر أنّ <code>std::adopt_lock</code> ليست بديلاً عن استخدام كائنات المزامنة التكرارية، فسيحرَّر كائن المزامنة عند خروج القفل عن النطاق.
</p>

<h4>
	الأقفال النطاقية std::scoped_lock ‏(C++ 17)
</h4>

<p>
	توفّر الأقفال النطاقية <code>std::scoped_lock</code> دلالات RAII لامتلاك كائن مزامنة أو أكثر، وتُستخدم مع خوارزميات تجنّب الشلل الوظيفي التي تستخدمها الأقفال العادية <code>‎std::lock‎</code>. وعندما تُدمَّر <code>‎std::scoped_lock‎</code>، فإن كائنات المزامنة تُحرّر بالترتيب العكسي لترتيب الحصول عليها.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_56" style="">
<span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">scoped_lock lock
    </span><span class="pun">{</span><span class="pln">
        _mutex1</span><span class="pun">,</span><span class="pln"> _mutex2
    </span><span class="pun">};</span><span class="pln">
    </span><span class="com">// افعل شيئا ما</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	كائنات المزامنة التكرارية Recursive Mutex
</h3>

<p>
	تسمح كائنات المزامنة التكرارية لخيط ما بقفل أحد الموارد بدون حد معين، ولا توجد مبررات كثيرة لاستخدام هذه التقنية، لكن قد تحتاج بعض التنفيذات (implementations) المعقّدة إلى استدعاء نسخة <a data-ss1615541024="1" data-ss1615541531="1" data-ss1617023041="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-22-%D8%A7%D9%84%D8%AA%D8%AD%D9%85%D9%8A%D9%84-%D8%A7%D9%84%D8%B2%D8%A7%D8%A6%D8%AF-overloading-%D8%AA%D8%AD%D9%84%D9%8A%D9%84%D9%87-%D9%88%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D9%87-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D9%81%D9%8A-cpp-r934/" rel="">مُحمّلة تحميلا زائدًا</a> (overloaded) من دالّة دون تحرير القفل. انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_58" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">atomic_int temp
</span><span class="pun">{</span><span class="pln">
    </span><span class="lit">0</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">recursive_mutex _mutex</span><span class="pun">;</span></pre>

<p>
	تطلق <code>launch_deferred</code> مهامًا غير متزامنة على نفس معرِّف الخيط، تابع …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_60" style="">
<span class="kwd">auto</span><span class="pln"> future1 </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">async </span><span class="pun">(</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">launch</span><span class="pun">::</span><span class="pln">deferred</span><span class="pun">,</span><span class="pln">
</span><span class="pun">[</span><span class="pln"> </span><span class="pun">&amp;]()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">this_thread</span><span class="pun">::</span><span class="pln">get_id</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">this_thread</span><span class="pun">::</span><span class="pln">sleep_for</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">chrono</span><span class="pun">::</span><span class="pln">seconds</span><span class="pun">(</span><span class="lit">3</span><span class="pun">));</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">unique_lock</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">recursive_mutex </span><span class="pun">&gt;</span><span class="pln"> lock</span><span class="pun">(</span><span class="pln">_mutex</span><span class="pun">);</span><span class="pln">
        temp </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">});</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> future2 </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">async </span><span class="pun">(</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">launch</span><span class="pun">::</span><span class="pln">deferred</span><span class="pun">,</span><span class="pln">
</span><span class="pun">[</span><span class="pln"> </span><span class="pun">&amp;]()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">this_thread</span><span class="pun">::</span><span class="pln">get_id</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">this_thread</span><span class="pun">::</span><span class="pln">sleep_for</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">chrono</span><span class="pun">::</span><span class="pln">milliseconds</span><span class="pun">(</span><span class="lit">1</span><span class="pun">));</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">unique_lock</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">recursive_mutex </span><span class="pun">&gt;</span><span class="pln"> lock</span><span class="pun">(</span><span class="pln">_mutex</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">try_to_lock</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">temp </span><span class="pun">&lt;</span><span class="pln"> INT_MAX</span><span class="pun">)</span><span class="pln">
                temp</span><span class="pun">++;</span><span class="pln">
            cout </span><span class="pun">&lt;&lt;</span><span class="pln"> temp </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">

        </span><span class="pun">}</span><span class="pln"> </span><span class="pun">});</span><span class="pln">
future1</span><span class="pun">.</span><span class="pln">get</span><span class="pun">();</span><span class="pln">
future2</span><span class="pun">.</span><span class="pln">get</span><span class="pun">();</span></pre>

<h3>
	هياكل مزامنة الخيوط
</h3>

<p>
	قد يتطلّب استعمال الخيوط أن تستخدم بعض تقنيات المزامنة إذا كانت الخيوط تتفاعل مع بعضها، وسنتحدث في هذا الموضوع عن عدد من الهياكل التي توفّرها المكتبة القياسية لحل هذه المشكلة.
</p>

<h4>
	std::condition_variable_any و std::cv_status
</h4>

<p>
	<code>‎std::condition_variable_any‎</code> هي تعميم لـ<code>‎std::condition_variable‎</code>، ويمكن أن تعمل مع أيّ نوع من الهياكل الأساسية القابلة للقفل (BasicLockable structure).
</p>

<p>
	و<code>std::cv_status</code> كقيمة مُعادة من متغيّر شرطي يكون لها رمزا إعادة (return codes) محتملان:
</p>

<ul>
<li>
		<code>std::cv_status::no_timeout</code>: إن لم تكن هناك مهلة (timeout)، وتمّ إشعارالمتغيّر الشرطي.
	</li>
	<li>
		<code>std::cv_status::timeout</code>: عند انتهاء مهلة المتغيّر الشرطي.
	</li>
</ul>
<h4>
	الأقفال المشتركة std::shared_lock
</h4>

<p>
	يمكن استخدام الأقفال المشتركة مع قفل حصريّ (unique lock) من أجل السماح بعدّة قارئات (readers)، لكن مع كاتبات (writers) حصرية.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_62" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;unordered_map&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;mutex&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;shared_mutex&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;thread&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;string&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">PhoneBook</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        string getPhoneNo</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&amp;</span><span class="pln">name</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            shared_lock</span><span class="str">&lt;shared_timed_mutex&gt;</span><span class="pln"> r</span><span class="pun">(</span><span class="pln">_protect</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">auto</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> _phonebook</span><span class="pun">.</span><span class="pln">find</span><span class="pun">(</span><span class="pln">name</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">it </span><span class="pun">==</span><span class="pln"> _phonebook</span><span class="pun">.</span><span class="pln">end</span><span class="pun">())</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(*</span><span class="pln">it</span><span class="pun">).</span><span class="pln">second</span><span class="pun">;</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="str">""</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">void</span><span class="pln"> addPhoneNo</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&amp;</span><span class="pln">name</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&amp;</span><span class="pln">phone</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        unique_lock</span><span class="str">&lt;shared_timed_mutex&gt;</span><span class="pln"> w</span><span class="pun">(</span><span class="pln">_protect</span><span class="pun">);</span><span class="pln">
        _phonebook</span><span class="pun">[</span><span class="pln">name</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> phone</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    shared_timed_mutex _protect</span><span class="pun">;</span><span class="pln">
    unordered_map</span><span class="pun">&lt;</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> string</span><span class="pun">&gt;</span><span class="pln"> _phonebook</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<h4>
	std::call_once و std::once_ﬂag
</h4>

<p>
	تضمن <code>std::call_once</code> ألّا تُنفّذ دالّة معيّنة إلّا مرّة واحدة فقط من قبل الخيوط المتنافسة (competing threads). وتطلق خطأ نظامي <code>std::system_error</code> في حال حدث ذلك. كذلك فإن <code>std::call_once</code> تُستخدم مع <code>‎td::once_flag‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_64" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;mutex&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">once_flag flag</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> do_something</span><span class="pun">(){</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">call_once</span><span class="pun">(</span><span class="pln">flag</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[](){</span><span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Happens once"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;});</span><span class="pln">

    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Happens every time"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h4>
	قفل الكائنات لتحسين كفاءة الوصول
</h4>

<p>
	قد ترغب في قفل الكائن بالكامل أثناء إجراء عمليات متعدّدة عليه، كأن تريد فحصه أو تعديله باستخدام المُكرّرات. وإن كنت بحاجة إلى استدعاء عدّة توابع، فمن الأفضل عمومًا قفله بالكامل بدلاً قفل التوابع فرديّا، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_66" style="">
<span class="kwd">class</span><span class="pln"> text_buffer
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// لأجل تحسين القراءة والصيانة</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> mutex_type </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">shared_timed_mutex</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> reading_lock </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">shared_lock</span><span class="str">&lt;mutex_type&gt;</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> updates_lock </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">unique_lock</span><span class="str">&lt;mutex_type&gt;</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span></pre>

<p>
	يعيد هذا قفلًا نطاقيًا (scoped lock) تستطيع عدة قارئات أن تتشاركه مع استثناء الكاتبات في نفس الوقت، تابع المثال …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_68" style="">
<span class="pln">    </span><span class="pun">[[</span><span class="pln">nodiscard</span><span class="pun">]]</span><span class="pln">
    reading_lock lock_for_reading</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> reading_lock</span><span class="pun">(</span><span class="pln">mtx</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	يعيد هذا قفلًا نطاقيًا خاصًا بكاتب واحد، مع منع القارئات، تابع …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_70" style="">
<span class="pln">    </span><span class="pun">[[</span><span class="pln">nodiscard</span><span class="pun">]]</span><span class="pln">
    updates_lock lock_for_updates</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> updates_lock</span><span class="pun">(</span><span class="pln">mtx</span><span class="pun">);</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> data</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> buf</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">char</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">*</span><span class="pln"> data</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> buf</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> begin</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> buf</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">char</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">*</span><span class="pln"> begin</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> buf</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> end</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> buf </span><span class="pun">+</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">buf</span><span class="pun">);</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">char</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">*</span><span class="pln"> end</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> buf </span><span class="pun">+</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">buf</span><span class="pun">);</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

    std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> size</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">buf</span><span class="pun">);</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">char</span><span class="pln"> buf</span><span class="pun">[</span><span class="lit">1024</span><span class="pun">];</span><span class="pln">
    </span><span class="kwd">mutable</span><span class="pln"> mutex_type mtx</span><span class="pun">;</span><span class="pln">    </span><span class="com">// للكائنات الثابتة بأن تُقفَل mutable يسمح</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	يسمح <code>mutable</code> في السطر الأخير الشيفرة أعلاه بأن تُقفَل الكائنات الثابتة، ويُقفل الكائن عند حساب المجموع (checksum) من أجل القراءة، وهذا سيفسح المجال أمام الخيوط الأخرى التي ترغب في القراءة من الكائن في نفس الوقت بأن تقرأ منه.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_72" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> checksum</span><span class="pun">(</span><span class="pln">text_buffer </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">buf</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> sum </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0xA44944A4</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// قفل الكائن لأجل القراءة</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> lock </span><span class="pun">=</span><span class="pln"> buf</span><span class="pun">.</span><span class="pln">lock_for_reading</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> c</span><span class="pun">:</span><span class="pln"> buf</span><span class="pun">)</span><span class="pln">
        sum </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">sum </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">8</span><span class="pun">)</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="pun">(((</span><span class="kwd">unsigned</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">)((</span><span class="pln">sum </span><span class="pun">&amp;</span><span class="pln"> </span><span class="lit">0xFF000000</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">24</span><span class="pun">))</span><span class="pln"> </span><span class="pun">^</span><span class="pln"> c</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> sum</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ويؤدّي مسح الكائن إلى تحديث بياناته الداخلية، لذا يجب فعل ذلك باستخدام قفل حصري.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_74" style="">
<span class="kwd">void</span><span class="pln"> clear</span><span class="pun">(</span><span class="pln">text_buffer </span><span class="pun">&amp;</span><span class="pln"> buf</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> lock </span><span class="pun">=</span><span class="pln"> buf</span><span class="pun">.</span><span class="pln">lock_for_updates</span><span class="pun">();</span><span class="pln">    </span><span class="com">// قفل حصري</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">fill</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">begin</span><span class="pun">(</span><span class="pln">buf</span><span class="pun">),</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">end</span><span class="pun">(</span><span class="pln">buf</span><span class="pun">),</span><span class="pln"> </span><span class="str">'\0'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يجب توخي الحذر دائمًا عند الحصول على أكثر من قفل، والحرص على الحصول على الأقفال بنفس الترتيب لجميع الخيوط.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_76" style="">
<span class="kwd">void</span><span class="pln"> transfer</span><span class="pun">(</span><span class="pln">text_buffer </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">input</span><span class="pun">,</span><span class="pln"> text_buffer </span><span class="pun">&amp;</span><span class="pln">output</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> lock1 </span><span class="pun">=</span><span class="pln"> input</span><span class="pun">.</span><span class="pln">lock_for_reading</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> lock2 </span><span class="pun">=</span><span class="pln"> output</span><span class="pun">.</span><span class="pln">lock_for_updates</span><span class="pun">();</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">copy</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">begin</span><span class="pun">(</span><span class="pln">input</span><span class="pun">),</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">end</span><span class="pun">(</span><span class="pln">input</span><span class="pun">),</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">begin</span><span class="pun">(</span><span class="pln">output</span><span class="pun">));</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>ملاحظة</strong>: من الأفضل إنجاز ذلك باستخدام <code>std::deferred::lock</code> ثمّ استدعاء <code>std::lock</code>
</p>

<h3>
	متغير تقييد الوصول
</h3>

<p>
	متغير تقييد الوصول (Semaphore) غير متاح حاليًا في C++‎، ولكن يمكن تنفيذه بسهولة باستخدام كائنات المزامنة والمتغيّرات الشرطية. هذا المثال مأخوذ من:
</p>

<ul>
<li>
		<a data-ss1615541024="1" data-ss1615541531="1" data-ss1617023041="1" href="https://stackoverflow.com/questions/4792449/c0x-has-no-semaphores-how-to-synchronize-threads" rel="external nofollow">C++0x has no semaphores? How to synchronize threads</a>
	</li>
</ul>
<h4>
	متغيرات تقييد الوصول في C++‎ 11
</h4>

<p>
	انظر المثال التوضيحي التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_78" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;mutex&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;condition_variable&gt;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Semaphore</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Semaphore</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> count_ </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">):</span><span class="pln"> count</span><span class="pun">(</span><span class="pln">count_</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

    </span><span class="kwd">inline</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> notify</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> tid</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">unique_lock</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">mutex </span><span class="pun">&gt;</span><span class="pln"> lock</span><span class="pun">(</span><span class="pln">mtx</span><span class="pun">);</span><span class="pln">
        count</span><span class="pun">++;</span><span class="pln">
        cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"thread "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> tid </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" notify"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
        </span><span class="com">//أشعِر الخيط المنتظِر.</span><span class="pln">
        cv</span><span class="pun">.</span><span class="pln">notify_one</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">inline</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> wait</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> tid</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">unique_lock</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">mutex </span><span class="pun">&gt;</span><span class="pln"> lock</span><span class="pun">(</span><span class="pln">mtx</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">count </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"thread "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> tid </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" wait"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
            </span><span class="com">// notify انتظر كائن المزامنة إلى حين استدعاء</span><span class="pln">
            cv</span><span class="pun">.</span><span class="pln">wait</span><span class="pun">(</span><span class="pln">lock</span><span class="pun">);</span><span class="pln">
            cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"thread "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> tid </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" run"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        count</span><span class="pun">--;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">mutex mtx</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">condition_variable cv</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> count</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<h4>
	مثال على استخدام متغير تقييد الوصول
</h4>

<p>
	تضيف الدالّة التالية أربعة خيوط، تتنافس ثلاثة منها على متغير تقييد الوصول الذي يُضبط عدّاده عند القيمة 1. وسيستدعي الخيط الأبطأ <code>‎notify_one()‎</code>، ممّا يسمح لأحد الخيوط المنتظِرة بالمتابعة.
</p>

<p>
	ونتيجة لهذا تبدأ <code>‎s1‎</code> على الفور، مما سيُبقي عدّاد متغير تقييد الوصول <code>‎count‎</code> دون القيمة 1، وستنتظر الخيوط الأخرى دورها في المتغيّر الشرطي حتى استدعاء <code>notify()‎‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_80" style="">
<span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Semaphore</span><span class="pln"> sem</span><span class="pun">(</span><span class="lit">1</span><span class="pun">);</span><span class="pln">

    thread s1</span><span class="pun">([</span><span class="pln"> </span><span class="pun">&amp;]()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            this_thread</span><span class="pun">::</span><span class="pln">sleep_for</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">chrono</span><span class="pun">::</span><span class="pln">seconds</span><span class="pun">(</span><span class="lit">5</span><span class="pun">));</span><span class="pln">
            sem</span><span class="pun">.</span><span class="pln">wait</span><span class="pun">(</span><span class="lit">1</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln"> </span><span class="pun">});</span><span class="pln">
    thread s2</span><span class="pun">([</span><span class="pln"> </span><span class="pun">&amp;]()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            sem</span><span class="pun">.</span><span class="pln">wait</span><span class="pun">(</span><span class="lit">2</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln"> </span><span class="pun">});</span><span class="pln">
    thread s3</span><span class="pun">([</span><span class="pln"> </span><span class="pun">&amp;]()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            this_thread</span><span class="pun">::</span><span class="pln">sleep_for</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">chrono</span><span class="pun">::</span><span class="pln">milliseconds</span><span class="pun">(</span><span class="lit">600</span><span class="pun">));</span><span class="pln">
            sem</span><span class="pun">.</span><span class="pln">wait</span><span class="pun">(</span><span class="lit">3</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln"> </span><span class="pun">});</span><span class="pln">
    thread s4</span><span class="pun">([</span><span class="pln"> </span><span class="pun">&amp;]()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            this_thread</span><span class="pun">::</span><span class="pln">sleep_for</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">chrono</span><span class="pun">::</span><span class="pln">seconds</span><span class="pun">(</span><span class="lit">5</span><span class="pun">));</span><span class="pln">
            sem</span><span class="pun">.</span><span class="pln">notify</span><span class="pun">(</span><span class="lit">4</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln"> </span><span class="pun">});</span><span class="pln">

    s1</span><span class="pun">.</span><span class="pln">join</span><span class="pun">();</span><span class="pln">
    s2</span><span class="pun">.</span><span class="pln">join</span><span class="pun">();</span><span class="pln">
    s3</span><span class="pun">.</span><span class="pln">join</span><span class="pun">();</span><span class="pln">
    s4</span><span class="pun">.</span><span class="pln">join</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">...</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	إنشاء ساحة خيوط بسيطة
</h2>

<p>
	خيوط C++‎ 11 الأساسية منخفضة المستوى نسبيًا، لذا يمكن استخدامها لكتابة كائنات عالية المستوى مثل ساحة الخيوط (thread pool):
</p>

<p>
	<strong>الإصدار ≥ C++‎ 14</strong>
</p>

<p>
	يشكل كائن المزامنة والمتغير الشرطي وكائن <code>deque</code> طابورًا من المهام آمن على الخيوط (thread-safe):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_82" style="">
<span class="kwd">struct</span><span class="pln"> tasks
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">mutex m</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">condition_variable v</span><span class="pun">;</span></pre>

<p>
	… لاحظ أن <code>&lt;packaged_task&lt;void</code> تستطيع تخزين <code>&lt;packaged_task&lt;R</code> … :
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_84" style="">
<span class="pln">    std</span><span class="pun">::</span><span class="pln">deque</span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">packaged_task </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&gt;&gt;</span><span class="pln"> work</span><span class="pun">;</span><span class="pln">
    </span><span class="com">//  هذا سيمثل العمل الذي أنجزته الخيوط</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">vector</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">future </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">&gt;&gt;</span><span class="pln"> finished</span><span class="pun">;</span></pre>

<p>
	<code>(queue (lambda</code> سيضيف لامدا إلى قائمة المهام التي سينفذها الخيط …:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_86" style="">
<span class="pln">     </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> F</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> R </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">result_of_t</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> F </span><span class="pun">&amp;()</span><span class="pln"> </span><span class="pun">&gt;&gt;</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">future</span><span class="pun">&lt;</span><span class="pln">R</span><span class="pun">&gt;</span><span class="pln"> </span><span class="typ">queue</span><span class="pun">(</span><span class="pln">F </span><span class="pun">&amp;&amp;</span><span class="pln"> f</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="com">// لتقسيم التنفيذ - packaged task - تغليف كائن الدالة في مهمة محزومة</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">packaged_task </span><span class="pun">&lt;</span><span class="pln"> R</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> p</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="pln">F</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">f</span><span class="pun">));</span><span class="pln">
            </span><span class="kwd">auto</span><span class="pln"> r </span><span class="pun">=</span><span class="pln"> p</span><span class="pun">.</span><span class="pln">get_future</span><span class="pun">();</span><span class="pln">    </span><span class="com">// الحصول على القيمة من المهمة قيد تنفيذ </span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                std</span><span class="pun">::</span><span class="pln">unique_lock</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">mutex </span><span class="pun">&gt;</span><span class="pln"> l</span><span class="pun">(</span><span class="pln">m</span><span class="pun">);</span></pre>

<p>
	سنخزن المهمة <code>&lt;()R&gt;</code> على شكل <code>&lt;()void&gt;</code>، تابع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_88" style="">
<span class="pln">                work</span><span class="pun">.</span><span class="pln">emplace_back</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">p</span><span class="pun">));</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">

            v</span><span class="pun">.</span><span class="pln">notify_one</span><span class="pun">();</span><span class="pln">    </span><span class="com">// إيقاظ الخيط ليعمل على المهمة</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> r</span><span class="pun">;</span><span class="pln">    </span><span class="com">// إعادة النتيجة المستقبلية للمهمة</span><span class="pln">
        </span><span class="pun">}</span></pre>

<p>
	والآن، نبدأ عدد N من الخيوط في ساحة الخيوط، نتابع المثال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_90" style="">
<span class="pln">    </span><span class="kwd">void</span><span class="pln"> start</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> N </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> N</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span></pre>

<p>
	كل الخيوط الآن غير متزامنة <code>std::async</code>، وتنفذ <code>()this-&gt;thread_task</code>، تابع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_92" style="">
<span class="pln">            finished</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">
                std</span><span class="pun">::</span><span class="pln">async </span><span class="pun">(</span><span class="pln">
                    std</span><span class="pun">::</span><span class="pln">launch</span><span class="pun">::</span><span class="pln">async</span><span class="pun">,</span><span class="pln">
                </span><span class="pun">[</span><span class="kwd">this</span><span class="pun">]</span><span class="pln">
                    </span><span class="pun">{</span><span class="pln">
                        thread_task</span><span class="pun">();</span><span class="pln">
                    </span><span class="pun">}</span><span class="pln">
            </span><span class="pun">)</span><span class="pln">
        </span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	تلغي <code>()abort</code> كل المهام التي لم تنطلق بعد، وإخطار كل الخيوط العاملة أن تتوقف، وتنتظرهم حتى ينتهوا، تابع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_94" style="">
<span class="pln">  </span><span class="kwd">void</span><span class="pln"> abort</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        cancel_pending</span><span class="pun">();</span><span class="pln">
        finish</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	تلغي <code>()cancel_pending</code> المهام التي لم تنطلق بعد:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_96" style="">
<span class="pln">    </span><span class="kwd">void</span><span class="pln"> cancel_pending</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">unique_lock</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">mutex </span><span class="pun">&gt;</span><span class="pln"> l</span><span class="pun">(</span><span class="pln">m</span><span class="pun">);</span><span class="pln">
        work</span><span class="pun">.</span><span class="pln">clear</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	هنا نرسل رسالة "stop the thread" إلى جميع الخيوط، ثم نتظرها، تابع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_98" style="">
<span class="pln">    </span><span class="kwd">void</span><span class="pln"> finish</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">unique_lock</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">mutex </span><span class="pun">&gt;</span><span class="pln"> l</span><span class="pun">(</span><span class="pln">m</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> unused</span><span class="pun">:</span><span class="pln"> finished</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                work</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln"> </span><span class="pun">{});</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        v</span><span class="pun">.</span><span class="pln">notify_all</span><span class="pun">();</span><span class="pln">
        finished</span><span class="pun">.</span><span class="pln">clear</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}~</span><span class="pln">tasks</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        finish</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="com">//: العمل الذي يقوم به الخيط قيد التنفيذ</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> thread_task</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="com">// سحب مهمة من الطابور</span><span class="pln">
                std</span><span class="pun">::</span><span class="pln">packaged_task </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> f</span><span class="pun">;</span><span class="pln">
                </span><span class="pun">{</span><span class="pln">
                    std</span><span class="pun">::</span><span class="pln">unique_lock</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">mutex </span><span class="pun">&gt;</span><span class="pln"> l</span><span class="pun">(</span><span class="pln">m</span><span class="pun">);</span><span class="pln">
                    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">work</span><span class="pun">.</span><span class="pln">empty</span><span class="pun">())</span><span class="pln">
                    </span><span class="pun">{</span><span class="pln">
                        v</span><span class="pun">.</span><span class="pln">wait</span><span class="pun">(</span><span class="pln">l</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[&amp;</span><span class="pln"> </span><span class="pun">]</span><span class="pln">
                        </span><span class="pun">{</span><span class="pln">
                            </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">!</span><span class="pln">work</span><span class="pun">.</span><span class="pln">empty</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">});</span><span class="pln">
                    </span><span class="pun">}</span><span class="pln">

                    f </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">work</span><span class="pun">.</span><span class="pln">front</span><span class="pun">());</span><span class="pln">
                    work</span><span class="pun">.</span><span class="pln">pop_front</span><span class="pun">();</span><span class="pln">
                </span><span class="pun">}</span><span class="pln">

                </span><span class="com">// إذا كانت المهمة غير صالحة، فسيكون علينا إلغاؤها</span><span class="pln">
                </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">f</span><span class="pun">.</span><span class="pln">valid</span><span class="pun">())</span><span class="pln"> </span><span class="kwd">return</span><span class="pun">;</span><span class="pln">
                </span><span class="com">// خلاف ذلك، ينبغي تنفيذ المهمة</span><span class="pln">
                f</span><span class="pun">();</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	تعيد الدالة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5686_7" style="">
<span class="pln">tasks</span><span class="pun">.</span><span class="typ">queue</span><span class="pun">(</span><span class="pln"> </span><span class="pun">[]{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="str">"hello world"</span><span class="pln">s</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="pun">)</span></pre>

<p>
	<code>‎‎</code>قيمة من النوع <code>std::future&lt;std::string&gt;‎</code>، والتي ستساوي عند تنفيذ كائن المهام السلسلة النصية <code>‎hello world‎</code>. كذلك يمكنك إنشاء الخيوط عن طريق تنفيذ <code>‎tasks.start(10)‎</code> (والتي تطلق 10 خيوط).
</p>

<p>
	إن سبب استخدام <code>‎packaged_task&lt;void()&gt;‎</code>هو أنّه لا يوجد قالب صنف <code>‎std::function‎</code>‏ مكافئ ومشطوب النوع (type-erased)، ولا يخزّن إلّا أنواع النقل فقط (move-only types). أيضًا، قد تكون كتابة نوع مخصّص أسرع من استخدام <code>‎packaged_task&lt;void()&gt;‎</code>.
</p>

<p>
	<a data-ss1615541024="1" data-ss1615541531="1" data-ss1617023041="1" href="coliru.stacked-crooked.com/" rel="">انظر هذا المثال الحيّ</a> على ذلك.
</p>

<p>
	<strong>الإصدار = C++‎ 11</strong>
</p>

<p>
	في C++‎ 11، استبدل <code>‎result_of_t&lt;blah&gt;‎</code> بـ <code>‎typename result_of&lt;blah&gt;::type‎</code>.
</p>

<h2>
	التحقق من أنّ الخيط مضموم دائمًا
</h2>

<p>
	عند استدعاء مدمَّر <code>‎std::thread‎</code>، يجب استدعاء <code>‎join()‎</code> أو <code>‎detach()‎</code>. وإذا لم يُضمّ (joined) الخيط أو يُفصل (detached)، فستُستدعى <code>‎std::terminate‎</code> افتراضيًا. يمكن تسهيل هذا عبر استخدام <a data-ss1615541024="1" data-ss1615541531="1" data-ss1617023041="1" href="https://en.cppreference.com/w/cpp/language/raii" rel="external nofollow">RAII</a>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_100" style="">
<span class="kwd">class</span><span class="pln"> thread_joiner
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        thread_joiner</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">thread t</span><span class="pun">):</span><span class="pln"> t_</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">t</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="pun">~</span><span class="pln">thread_joiner</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">t_</span><span class="pun">.</span><span class="pln">joinable</span><span class="pun">())</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                t_</span><span class="pun">.</span><span class="pln">join</span><span class="pun">();</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">thread t_</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ثم يمكن كتابة ما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_102" style="">
<span class="kwd">void</span><span class="pln"> perform_work</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// إنجاز عمل ما</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> t</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    thread_joiner j
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">thread</span><span class="pun">(</span><span class="pln">perform_work</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
    </span><span class="com">// تنفيذ بعض الحسابات أثناء تنفيذ الخيط</span><span class="pln">
</span><span class="pun">}</span><span class="pln">    </span><span class="com">// يُضمّ الخيط هنا تلقائيا</span></pre>

<p>
	يوفّر هذا أيضًا أمان الاعتراضات (exception safety)؛ ذلك أنّه إذا أنشأنا الخيط بشكل طبيعي ثمّ تسبّب العمل المُنجَز في <code>‎t()‎</code> برفع اعتراض، فلن تُستدعى <code>‎join()‎</code> على خيطنا، ولن تكتمل العملية.
</p>

<h2>
	إجراء عمليات على الخيط الحالي
</h2>

<p>
	<code>std::this_thread</code> هي فضاء اسم (namespace) يحتوي بعض الدوالّ التي يمكن استخدامها لإجراء عمليات معيّنة على الخيط الحالي من الدالّة التي استُدعِي منها.
</p>

<table>
<thead><tr>
<th>
				الدالة
			</th>
			<th>
				الوصف
			</th>
		</tr></thead>
<tbody>
<tr>
<td>
				<code>get_id</code>
			</td>
			<td>
				تعيد معرِّف الخيط.
			</td>
		</tr>
<tr>
<td>
				<code>sleep_for</code>
			</td>
			<td>
				تجعل الخيط ينام لفترة محددة.
			</td>
		</tr>
<tr>
<td>
				<code>sleep_until</code>
			</td>
			<td>
				تجعل الخيط ينام "حتى" وقت محدد.
			</td>
		</tr>
<tr>
<td>
				<code>yield</code>
			</td>
			<td>
				إعادة جدولة الخيوط العاملة وإعطاء الأولوية لخيوط أخرى.
			</td>
		</tr>
</tbody>
</table>
<p>
	يمكنك الحصول على معُرّف الخيط الحالي باستخدام <code>‎std::this_thread::get_id‎</code>، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_104" style="">
<span class="kwd">void</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// اطبع معرّف الخيط</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">this_thread</span><span class="pun">::</span><span class="pln">get_id</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">thread thread
</span><span class="pun">{</span><span class="pln">
    foo
</span><span class="pun">};</span><span class="pln">
thread</span><span class="pun">.</span><span class="pln">join</span><span class="pun">();</span><span class="pln">    </span><span class="com">// 12556 طُبِع معرّف الخيط الآن، وسيكون شيئا يشبه</span><span class="pln">
foo</span><span class="pun">();</span><span class="pln">    </span><span class="com">// 2420 طُبِع معرّف الخيط الرئيسي الآن، وسيكون شيئا يشبه</span></pre>

<p>
	النوم لمدة 3 ثوانٍ باستخدام <code>‎std::this_thread::sleep_for‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_106" style="">
<span class="kwd">void</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">this_thread</span><span class="pun">::</span><span class="pln">sleep_for</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">chrono</span><span class="pun">::</span><span class="pln">seconds</span><span class="pun">(</span><span class="lit">3</span><span class="pun">));</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">thread thread
</span><span class="pun">{</span><span class="pln">
    foo
</span><span class="pun">};</span><span class="pln">
foo</span><span class="pun">.</span><span class="pln">join</span><span class="pun">();</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Waited for 3 seconds!\n"</span><span class="pun">;</span></pre>

<p>
	النوم إلى أن تنقضي 3 ساعات باستخدام <code>‎std::this_thread::sleep_until‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_108" style="">
<span class="kwd">void</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">this_thread</span><span class="pun">::</span><span class="pln">sleep_until</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">chrono</span><span class="pun">::</span><span class="pln">system_clock</span><span class="pun">::</span><span class="pln">now</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">chrono</span><span class="pun">::</span><span class="pln">hours</span><span class="pun">(</span><span class="lit">3</span><span class="pun">));</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">thread thread
</span><span class="pun">{</span><span class="pln">
    foo
</span><span class="pun">};</span><span class="pln">
thread</span><span class="pun">.</span><span class="pln">join</span><span class="pun">();</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"We are now located 3 hours after the thread has been called\n"</span><span class="pun">;</span></pre>

<p>
	منح الأولوية لخيوط أخرى باستخدام <code>‎std::this_thread::yield‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_110" style="">
<span class="kwd">void</span><span class="pln"> foo</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">&lt;</span><span class="pln">al</span><span class="pun">++</span><span class="pln">i</span><span class="pun">)</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">this_thread</span><span class="pun">::</span><span class="pln">yield</span><span class="pun">();</span><span class="pln">    </span><span class="com">// ستأخذ خيوط أخرى الأولوية الآن، لأنّ هذا الخيط لا يفعل أي شيء مهم</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Hello World!\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">thread thread
</span><span class="pun">{</span><span class="pln">
    foo</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
thread</span><span class="pun">.</span><span class="pln">join</span><span class="pun">();</span></pre>

<h2>
	استخدام المتغيرات الشرطية Using Condition Variables
</h2>

<p>
	المتغيّر الشرطي (condition variable) هو كائن أوّلي (primitive) يُستخدم مع كائن مزامنة (mutex) لتنظيم الاتصالات بين الخيوط. ورغم أنّها ليست الطريقة الوحيدة لفعل ذلك ولا الأكثر فعالية إلا أنّها تتميّز بالبساطة والسهولة.
</p>

<p>
	و يمكن انتظار المتغيرات الشرطية <code>‎std::condition_variable‎</code> عبر <code>‎std::unique_lock&lt;std::mutex&gt;‎</code>. فهذا يسمح للشيفرة بفحص الحالة المشتركة (shared state) بأمان قبل تقرير ما إذا كان يجب متابعة عملية الحصول (acquisition) على القفل أم لا.
</p>

<p>
	يستخدم المثال أدناه <code>‎std::thread‎</code> و <code>‎std::condition_variable‎</code> و <code>‎std::mutex‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_112" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;condition_variable&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;cstddef&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;mutex&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;queue&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;random&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;thread&gt;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">condition_variable cond</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">mutex mtx</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">queue</span><span class="str">&lt;int&gt;</span><span class="pln"> intq</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">bool</span><span class="pln"> stopped </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">thread producer
    </span><span class="pun">{</span><span class="pln">
    </span><span class="pun">[</span><span class="pln"> </span><span class="pun">&amp;]()</span><span class="pln">
        </span><span class="pun">{</span></pre>

<p>
	جهّز مولد الأعداد العشوائية، وسيدفع هذا المولد أعدادًا عشوائية إلى <code>intq</code>، تابع المثال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_114" style="">
<span class="pln">            std</span><span class="pun">::</span><span class="pln">default_random_engine gen </span><span class="pun">{};</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">uniform_int_distribution</span><span class="str">&lt;int&gt;</span><span class="pln"> dist </span><span class="pun">{};</span><span class="pln">
            std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> count </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4006</span><span class="pun">;</span><span class="pln">
            </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">count</span><span class="pun">--)</span><span class="pln">
            </span><span class="pun">{</span></pre>

<p>
	لابد من القفل قبل تغيير الحالة التي يحميها كائن المزامنة والمتغير الشرطي <code>condition_variable</code>، تابع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_116" style="">
<span class="pln">                std</span><span class="pun">::</span><span class="pln">lock_guard</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">mutex </span><span class="pun">&gt;</span><span class="pln"> L
                </span><span class="pun">{</span><span class="pln">
                    mtx
                </span><span class="pun">};</span><span class="pln">
                </span><span class="com">// وضع العدد العشوائي في الطابور</span><span class="pln">
                intq</span><span class="pun">.</span><span class="pln">push</span><span class="pun">(</span><span class="pln">dist</span><span class="pun">(</span><span class="pln">gen</span><span class="pun">));</span><span class="pln">
                cond</span><span class="pun">.</span><span class="pln">notify_one</span><span class="pun">();</span><span class="pln">
            </span><span class="pun">}</span></pre>

<p>
	الآن تم كل شيء، احصل على القفل وعين راية الإيقاف <code>stopped</code> ثم نبه المستخدم، تابع … :
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_118" style="">
<span class="pln">            std</span><span class="pun">::</span><span class="pln">lock_guard</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">mutex </span><span class="pun">&gt;</span><span class="pln"> L
            </span><span class="pun">{</span><span class="pln">
                mtx
            </span><span class="pun">};</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Producer is done!"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
            stopped </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
            cond</span><span class="pun">.</span><span class="pln">notify_one</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">thread consumer
    </span><span class="pun">{</span><span class="pln">
    </span><span class="pun">[</span><span class="pln"> </span><span class="pun">&amp;]()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">do</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                std</span><span class="pun">::</span><span class="pln">unique_lock</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">mutex </span><span class="pun">&gt;</span><span class="pln"> L
                </span><span class="pun">{</span><span class="pln">
                    mtx
                </span><span class="pun">};</span><span class="pln">
                cond</span><span class="pun">.</span><span class="pln">wait</span><span class="pun">(</span><span class="pln">L</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[&amp;</span><span class="pln"> </span><span class="pun">]()</span><span class="pln">
                </span><span class="pun">{</span><span class="pln">
                    </span><span class="com">// الاستحواذ على القفل في حال الانتهاء أو في حال لم يكن الطابور فارغا</span><span class="pln">
                    </span><span class="kwd">return</span><span class="pln"> stopped </span><span class="pun">||</span><span class="pln"> </span><span class="pun">!</span><span class="pln">intq</span><span class="pun">.</span><span class="pln">empty</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">});</span><span class="pln">
                </span><span class="com">// نحن نملك كائن المزامنة هنا</span><span class="pln">
                </span><span class="com">// سحب العناصر من الطابور إلى أن يصبح فارغا</span><span class="pln">
                </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">intq</span><span class="pun">.</span><span class="pln">empty</span><span class="pun">())</span><span class="pln">
                </span><span class="pun">{</span><span class="pln">
                    </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> val </span><span class="pun">=</span><span class="pln"> intq</span><span class="pun">.</span><span class="pln">front</span><span class="pun">();</span><span class="pln">
                    intq</span><span class="pun">.</span><span class="pln">pop</span><span class="pun">();</span><span class="pln">
                    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Consumer popped: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> val </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
                </span><span class="pun">}</span><span class="pln">

                </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">stopped</span><span class="pun">)</span><span class="pln">
                </span><span class="pun">{</span><span class="pln">
                    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Consumer is done!"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
                    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
                </span><span class="pun">}</span><span class="pln">
            </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">true</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
    consumer</span><span class="pun">.</span><span class="pln">join</span><span class="pun">();</span><span class="pln">
    producer</span><span class="pun">.</span><span class="pln">join</span><span class="pun">();</span><span class="pln">

    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Example Completed!"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	عمليات الخيوط Thread operations
</h2>

<p>
	عندما يبدأ تنفيد خيط معيّن، فسيُنفّذ إلى أن يكتمل، لكن قد تحتاج أحيانًا إلى انتظار اكتمال تنفيذ خيط ما إن كنت تريد استخدام النتيجة التي يعيدها. على سبيل المثال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_120" style="">
<span class="typ">int</span><span class="pln"> n</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">thread thread
</span><span class="pun">{</span><span class="pln">
    calculateSomething</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">ref</span><span class="pun">(</span><span class="pln">n</span><span class="pun">)</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// افعل أشياء أخرى</span></pre>

<p>
	… نحن نحتاج <code>n</code> الآن، انتظر الخيط إلى أن ينتهي، إن لم يكن قد انتهى فعلًا، وستكون قيمة <code>n</code> بعدها هي النتيجة المحسوبة في خيط آخر، تابع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_122" style="">
<span class="pln">thread</span><span class="pun">.</span><span class="pln">join</span><span class="pun">();</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> n </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span></pre>

<p>
	يمكنك أيضًا فصل (<code>‎detach‎</code>) الخيط، والسماح بأن يُنفّذ بحرّية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_124" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">thread thread
</span><span class="pun">{</span><span class="pln">
    doSomething
</span><span class="pun">};</span><span class="pln">
</span><span class="com">//فصل الخيط، فنحن لا نريده بعد الآن</span><span class="pln">
thread</span><span class="pun">.</span><span class="pln">detach</span><span class="pun">();</span><span class="pln">
</span><span class="com">// سيتم إنهاء الخيط عند اكتمال تنفيذه، أو عند عودة الخيط الرئيسي</span></pre>

<h2>
	التخزين المحلي للخيوط
</h2>

<p>
	يمكن إنشاء خيوط مُخزّنة محليًا باستخدام الكلمة المفتاحية <code>‎thread_local‎</code>، والمتغيّرات التي يُصرّح عنها بالمحدّد <code>‎thread_local‎</code> يُقال أنّ لها <strong>مدة تخزين خيطية</strong> (thread storage duration).
</p>

<ul>
<li>
		كل خيط في البرنامج له نسخته الخاصّة من كل متغيّر محلي في الخيط (thread-local variable).
	</li>
	<li>
		سيُهيّأ متغيّر الخيط المحلي الموجود في نطاق دالة (محلّية) بمجرّد تمرير التحكّم إلى تعريفها. هذا المتغيّر سيكون ساكنًا ضمنيًا ما لم يُصرّح عنه عبر <code>‎extern‎</code>.
	</li>
	<li>
		ستُهيّأ متغيّرات الخيط المحلي الموجودة في نطاق فضاء اسم أو نطاق صنف -غير محلي- عند بدء تنفيذ الخيط.
	</li>
	<li>
		تُدمّر متغيّرات الخيط المحلي عند اكتمال تنفيذ الخيط.
	</li>
	<li>
		لا يمكن لأعضاء صنف معيّن أن تكون محلية في الخيط (thread-local) إلا إن كانت ساكنة، وعندها ستكون هناك نسخة واحدة من ذلك المتغيّر لكل خيط، بدلاً من نسخة واحدة لكل زوج (نُسخة، خيط) [(thread, instance)]. انظر:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_126" style="">
<span class="kwd">void</span><span class="pln"> debug_counter</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    thread_local </span><span class="typ">int</span><span class="pln"> count </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">Logger</span><span class="pun">::</span><span class="pln">log</span><span class="pun">(</span><span class="str">"This function has been called %d times by this thread"</span><span class="pun">,</span><span class="pln"> </span><span class="pun">++</span><span class="pln">count</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	إعادة إسناد كائنات الخيوط
</h2>

<p>
	يمكننا إنشاء كائنات خيوط فارغة (empty thread objects)، وإسناد مهامّ معيّنة إليها لاحقًا. وإذا أسندت كائن خيط إلى خيط آخر نشط وقابل للضمّ <code>‎joinable‎</code>، فستُستدعى <code>‎std::terminate‎</code> تلقائيًا قبل استبدال الخيط. انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_128" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;thread&gt;</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">this_thread</span><span class="pun">::</span><span class="pln">sleep_for</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">chrono</span><span class="pun">::</span><span class="pln">seconds</span><span class="pun">(</span><span class="lit">3</span><span class="pun">));</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// إنشاء 100 كائن خيطي فارغ</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">thread executors</span><span class="pun">[</span><span class="lit">100</span><span class="pun">];</span><span class="pln">
</span><span class="com">// شيفرة هنا</span><span class="pln">
</span><span class="com">// إنشاء بعض الخيوط </span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">100</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// إذا لم يُسنَد خيط إلى هذا الكائن</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">executors</span><span class="pun">[</span><span class="pln">i</span><span class="pun">].</span><span class="pln">joinable</span><span class="pun">())</span><span class="pln">
        executors</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">thread</span><span class="pun">(</span><span class="pln">foo</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	الآجال والوعود (Futures and Promises)
</h2>

<p>
	تُستخدم الآجال (Futures) والوعود لنقل كائن من خيط إلى آخر.
</p>

<ul>
<li>
		يُضبط كائن الوعود <code>‎std::promise‎</code> من قِبل الخيط الذي يولّد النتيجة.
	</li>
	<li>
		يُستخدم كائن <code>‎std::future‎</code> لاسترداد قيمة، أو التحقّق من إتاحة قيمة ما، أو لإيقاف التنفيذ إلى حين إتاحة القيمة.
	</li>
</ul>
<h3>
	أصناف العمليات غير المتزامنة
</h3>

<ul>
<li>
		<code>std::async</code> : تنفذ عملية غير متزامنة.
	</li>
	<li>
		<code>std::future</code> : توفّر وصولًا إلى نتيجة عملية غير متزامنة.
	</li>
	<li>
		<code>std::promise</code> : تحزِم نتيجة العملية غير المتزامنة.
	</li>
	<li>
		<code>std::packaged_task</code> : تربط دالّة مع الوعد المرتبط بها في نوع القيمة المُعادة.
	</li>
</ul>
<p>
	ينشئ المثال التالي وعدًا لكي يستخدمه خيط آخر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_130" style="">
<span class="pun">{</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> promise </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">promise</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">();</span><span class="pln">

    </span><span class="kwd">auto</span><span class="pln"> producer </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">thread</span><span class="pun">([</span><span class="pln"> </span><span class="pun">&amp;]</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        promise</span><span class="pun">.</span><span class="pln">set_value</span><span class="pun">(</span><span class="str">"Hello World"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">});</span><span class="pln">

    </span><span class="kwd">auto</span><span class="pln"> future </span><span class="pun">=</span><span class="pln"> promise</span><span class="pun">.</span><span class="pln">get_future</span><span class="pun">();</span><span class="pln">

    </span><span class="kwd">auto</span><span class="pln"> consumer </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">thread</span><span class="pun">([</span><span class="pln"> </span><span class="pun">&amp;]</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> future</span><span class="pun">.</span><span class="pln">get</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">});</span><span class="pln">

    producer</span><span class="pun">.</span><span class="pln">join</span><span class="pun">();</span><span class="pln">
    consumer</span><span class="pun">.</span><span class="pln">join</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	مثال مؤجل غير متزامن
</h3>

<p>
	تقدّم الشيفرة التالية نسخة من <code>‎std::async‎</code>، إلّا أنّها تتصرف كما لو كانت <code>‎async‎</code> تُستدعى عبر سياسة الإطلاق المؤجّلة <code>‎deferred‎</code>. ليس لهذه الدالّة أيضًا سلوك الأجل (<code>‎future‎</code>) الخاص بـ <code>‎async‎</code>، ويمكن تدمير القيمة المستقبلية (<code>‎future‎</code>) المُعادة قبل الحصول على قيمتها.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_132" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> F</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> async_deferred</span><span class="pun">(</span><span class="pln">F</span><span class="pun">&amp;&amp;</span><span class="pln"> func</span><span class="pun">)-&gt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">future </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">func</span><span class="pun">())</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> result_type </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">func</span><span class="pun">());</span><span class="pln">
        </span><span class="kwd">auto</span><span class="pln"> promise </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">promise</span><span class="str">&lt;result_type&gt;</span><span class="pln"> </span><span class="pun">();</span><span class="pln">
        </span><span class="kwd">auto</span><span class="pln"> future </span><span class="pun">=</span><span class="pln"> promise</span><span class="pun">.</span><span class="pln">get_future</span><span class="pun">();</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">thread</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">bind</span><span class="pun">([=](</span><span class="pln">std</span><span class="pun">::</span><span class="pln">promise</span><span class="str">&lt;result_type&gt;</span><span class="pun">&amp;</span><span class="pln"> promise</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">try</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                promise</span><span class="pun">.</span><span class="pln">set_value</span><span class="pun">(</span><span class="pln">func</span><span class="pun">());</span></pre>

<p>
	لاحظ أن هذا لن يعمل مع <code>&lt;std::promise &lt;void</code> إذ يحتاج برمجة القوالب الوصفية (meta-template programming)، تابع المثال …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_134" style="">
<span class="pln">                which is out of scope
                </span><span class="kwd">for</span><span class="pln"> </span><span class="kwd">this</span><span class="pln"> example</span><span class="pun">.</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">

            </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(...)</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                promise</span><span class="pun">.</span><span class="pln">set_exception</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">current_exception</span><span class="pun">());</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">},</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">promise</span><span class="pun">))).</span><span class="pln">detach</span><span class="pun">();</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> future</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span></pre>

<h3>
	std::packaged_task و std::future
</h3>

<p>
	تحزم <code>std::packaged_task</code> دالّة مع الوعد المرتبط بها في نوع القيمة المُعادة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_136" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> F</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> async_deferred</span><span class="pun">(</span><span class="pln">F</span><span class="pun">&amp;&amp;</span><span class="pln"> func</span><span class="pun">)-&gt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">future </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">func</span><span class="pun">())</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">auto</span><span class="pln"> task </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">packaged_task </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">func</span><span class="pun">())()</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="pln">F</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">func</span><span class="pun">));</span><span class="pln">
        </span><span class="kwd">auto</span><span class="pln"> future </span><span class="pun">=</span><span class="pln"> task</span><span class="pun">.</span><span class="pln">get_future</span><span class="pun">();</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">thread</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">task</span><span class="pun">)).</span><span class="pln">detach</span><span class="pun">();</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">future</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	يبدأ الخيط في العمل فورًا، ونستطيع فصله أو ضمّه في نهاية النطاق، وتكون النتيجة جاهزة عند انتهاء استدعاء الدالّة لـ <code>std::thread ﬁnishes</code>. لاحظ أنّ هذا يختلف قليلاً عن <code>‎std::async‎</code>، إذ أنّه عند تدمير الأجل <code>‎std::future‎</code> المُعاد، فسيُعطّل (block) إلى أن ينتهي الخيط.
</p>

<h2>
	std::future_error و std::future_errc
</h2>

<p>
	إذا لم تُستوفى قيود الوعود (<code>std::promise</code>) والآجال (<code>std::future</code>)، فسيُطرَح استثناء من النوع <code>std::future_error</code>. وسيكون رمز الخطأ في الاستثناء من النوع <code>std::future_errc</code>، وستكون القيم على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_138" style="">
<span class="kwd">enum</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> future_errc
</span><span class="pun">{</span><span class="pln">
broken_promise </span><span class="pun">=</span><span class="pln">             </span><span class="com">/* لم تعُد المهمّة مُشتركة */</span><span class="pun">,</span><span class="pln">
future_already_retrieved </span><span class="pun">=</span><span class="pln">         </span><span class="com">/* تم استرداد القيمة المُعادة سلفا */</span><span class="pun">,</span><span class="pln">
promise_already_satisfied </span><span class="pun">=</span><span class="pln">     </span><span class="com">/* الإجابة خُزِّنت سلفا */</span><span class="pun">,</span><span class="pln">
no_state </span><span class="pun">=</span><span class="pln">                 </span><span class="com">/* محاولة الدخول إلى وعد في حالة غير مشتركة */</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	انظر الأمثلة التوضيحية التالية:
</p>

<ul>
<li>
		الوعود غير النشطة (Inactive promise)
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_140" style="">
<span class="typ">int</span><span class="pln"> test</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">promise</span><span class="str">&lt;int&gt;</span><span class="pln"> pr</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">    </span><span class="com">// ok تعيد </span><span class="pln">
</span><span class="pun">}</span></pre>

<ul>
<li>
		الوعود النشطة غير المستخدمة:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_142" style="">
<span class="typ">int</span><span class="pln"> test</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">promise</span><span class="str">&lt;int&gt;</span><span class="pln"> pr</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> fut </span><span class="pun">=</span><span class="pln"> pr</span><span class="pun">.</span><span class="pln">get_future</span><span class="pun">();</span><span class="pln">    </span><span class="com">// تعطيل إلى أجل غير مسمى.</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<ul>
<li>
		الاسترجاع المزدوج Double retrieval
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_144" style="">
<span class="typ">int</span><span class="pln"> test</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">promise</span><span class="str">&lt;int&gt;</span><span class="pln"> pr</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> fut1 </span><span class="pun">=</span><span class="pln"> pr</span><span class="pun">.</span><span class="pln">get_future</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">try</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">auto</span><span class="pln"> fut2 </span><span class="pun">=</span><span class="pln"> pr</span><span class="pun">.</span><span class="pln">get_future</span><span class="pun">();</span><span class="pln">    </span><span class="com">// future محاولة ثانية للحصول على</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">future_error</span><span class="pun">&amp;</span><span class="pln"> e</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        cout </span><span class="pun">&lt;&lt;</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">what</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">    </span><span class="com">//     Error: "The future has already been retrieved from the promise or packaged_task."</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> fut2</span><span class="pun">.</span><span class="pln">get</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<ul>
<li>
		تعيين قيمة الوعد مرتين:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_146" style="">
<span class="typ">int</span><span class="pln"> test</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">promise</span><span class="str">&lt;int&gt;</span><span class="pln"> pr</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> fut </span><span class="pun">=</span><span class="pln"> pr</span><span class="pun">.</span><span class="pln">get_future</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">try</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">promise</span><span class="str">&lt;int&gt;</span><span class="pln"> pr2</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">pr</span><span class="pun">));</span><span class="pln">
        pr2</span><span class="pun">.</span><span class="pln">set_value</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln">
        pr2</span><span class="pun">.</span><span class="pln">set_value</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln">    </span><span class="com">// محاولة ثانية لتعيين قيمة الوعد، وهذا سيؤدي إلى رفع اعتراض.</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">future_error</span><span class="pun">&amp;</span><span class="pln"> e</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
      cout </span><span class="pun">&lt;&lt;</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">what</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// Error: "The state of the promise has already been</span><span class="pln">
               </span><span class="com">//  set."</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> fut</span><span class="pun">.</span><span class="pln">get</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	std::future و std::async
</h3>

<p>
	تُستخدَم <code>‎std::async‎</code> في مثال الترتيب المتوازي التالي لإطلاق عدّة مهام <code>merge_sort</code> متوازية، وتُستخدَم <code>std::future</code> لانتظار النتائج ومزامنتها:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_148" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> std</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> merge</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> low</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> mid</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> high</span><span class="pun">,</span><span class="pln"> </span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">num</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> copy</span><span class="pun">(</span><span class="pln">num</span><span class="pun">.</span><span class="pln">size</span><span class="pun">());</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> h</span><span class="pun">,</span><span class="pln"> i</span><span class="pun">,</span><span class="pln"> j</span><span class="pun">,</span><span class="pln"> k</span><span class="pun">;</span><span class="pln">
    h </span><span class="pun">=</span><span class="pln"> low</span><span class="pun">;</span><span class="pln">
    i </span><span class="pun">=</span><span class="pln"> low</span><span class="pun">;</span><span class="pln">
    j </span><span class="pun">=</span><span class="pln"> mid </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">((</span><span class="pln">h </span><span class="pun">&lt;=</span><span class="pln"> mid</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">j </span><span class="pun">&lt;=</span><span class="pln"> high</span><span class="pun">))</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">num</span><span class="pun">[</span><span class="pln">h</span><span class="pun">]</span><span class="pln"> </span><span class="pun">&lt;=</span><span class="pln"> num</span><span class="pun">[</span><span class="pln">j</span><span class="pun">])</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            copy</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> num</span><span class="pun">[</span><span class="pln">h</span><span class="pun">];</span><span class="pln">
            h</span><span class="pun">++;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">else</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            copy</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> num</span><span class="pun">[</span><span class="pln">j</span><span class="pun">];</span><span class="pln">
            j</span><span class="pun">++;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        i</span><span class="pun">++;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">h </span><span class="pun">&gt;</span><span class="pln"> mid</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">k </span><span class="pun">=</span><span class="pln"> j</span><span class="pun">;</span><span class="pln"> k </span><span class="pun">&lt;=</span><span class="pln"> high</span><span class="pun">;</span><span class="pln"> k</span><span class="pun">++)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            copy</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> num</span><span class="pun">[</span><span class="pln">k</span><span class="pun">];</span><span class="pln">
            i</span><span class="pun">++;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">else</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">k </span><span class="pun">=</span><span class="pln"> h</span><span class="pun">;</span><span class="pln"> k </span><span class="pun">&lt;=</span><span class="pln"> mid</span><span class="pun">;</span><span class="pln"> k</span><span class="pun">++)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            copy</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> num</span><span class="pun">[</span><span class="pln">k</span><span class="pun">];</span><span class="pln">
            i</span><span class="pun">++;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">k </span><span class="pun">=</span><span class="pln"> low</span><span class="pun">;</span><span class="pln"> k </span><span class="pun">&lt;=</span><span class="pln"> high</span><span class="pun">;</span><span class="pln"> k</span><span class="pun">++)</span><span class="pln">
        swap</span><span class="pun">(</span><span class="pln">num</span><span class="pun">[</span><span class="pln">k</span><span class="pun">],</span><span class="pln"> copy</span><span class="pun">[</span><span class="pln">k</span><span class="pun">]);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> merge_sort</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> low</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> high</span><span class="pun">,</span><span class="pln"> </span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">num</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> mid</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">low </span><span class="pun">&lt;</span><span class="pln"> high</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        mid </span><span class="pun">=</span><span class="pln"> low </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">high </span><span class="pun">-</span><span class="pln"> low</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">auto</span><span class="pln"> future1 </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">async </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">launch</span><span class="pun">::</span><span class="pln">deferred</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[&amp;</span><span class="pln"> </span><span class="pun">]()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            merge_sort</span><span class="pun">(</span><span class="pln">low</span><span class="pun">,</span><span class="pln"> mid</span><span class="pun">,</span><span class="pln"> num</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">});</span><span class="pln">
        </span><span class="kwd">auto</span><span class="pln"> future2 </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">async </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">launch</span><span class="pun">::</span><span class="pln">deferred</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[&amp;</span><span class="pln"> </span><span class="pun">]()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            merge_sort</span><span class="pun">(</span><span class="pln">mid </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> high</span><span class="pun">,</span><span class="pln"> num</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">});</span><span class="pln">

        future1</span><span class="pun">.</span><span class="pln">get</span><span class="pun">();</span><span class="pln">
        future2</span><span class="pun">.</span><span class="pln">get</span><span class="pun">();</span><span class="pln">
        merge</span><span class="pun">(</span><span class="pln">low</span><span class="pun">,</span><span class="pln"> mid</span><span class="pun">,</span><span class="pln"> high</span><span class="pun">,</span><span class="pln"> num</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>ملاحظة</strong>: في المثال أعلاه، تُطلَق <code>‎std::async‎</code> وفق سياسة <code>‎std::launch_deferred‎</code>، وذلك لتجنّب إنشاء خيط جديد في كل استدعاء، فتُجرى في مثالنا السابق استدعاءات <code>‎std::async‎</code> دون ترتيب، إذ أنّها تُزامن في استدعاءات <code>‎std::future::get()‎</code>. بالمقابل، تفرض <code>std::launch_async</code> إنشاء خَيط جديد في كل استدعاء.
</p>

<p>
	السياسة الافتراضية هي <code>‎std::launch::deferred| std::launch::async‎</code>، ممّا يعني أن التقديم سيكون هو المسؤول عن تحديد سياسة إنشاء الخيوط الجديدة.
</p>

<h2 id="-openmp">
	التزامن عبر OpenMP
</h2>

<p>
	يغطي هذا الموضوع أساسيات التزامن في C++‎ باستخدام OpenMP، والتوازي أو التزامن يعني تنفيذ الشيفرة في نفس الوقت.
</p>

<h3 id="openmp-">
	OpenMP: الأقسام المتوازية
</h3>

<p>
	يوضّح هذا المثال أساسيات تنفيذ أقسام (sections) من الشيفرة بالتوازي. ستعمل ميزة OpenMP على كل المصرِّفات المدعومة دون الحاجة إلى تضمين مكتبات بما أنها مبنية مسبقًا في المصرفات، لكن قد ترغب في تضمين <code>‎omp.h‎</code> إذا كنت تريد استخدام ميزات الواجهة البرمجية لـ openMP.
</p>

<p>
	انظر المثال التوضيحي التالي: ستلمِّح تعليمة <code>pragna</code> للمصرف أن المحتوى الموجود داخل { } سينفَّذ في أقسام متوازية باستخدام OpenMP، وسيولِّد المصرِّف هذه الشيفرة من أجل تنفيذها بالتوازي ...
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6216_7" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"begin "</span><span class="pun">;</span><span class="pln">
</span><span class="com">#pragma</span><span class="pln"> omp parallel sections
</span><span class="pun">{</span></pre>

<p>
	وهنا تلمِّح تعليمة <code>pragma</code> للمصرف أن هذا القسم يمكن تنفيذه بالتوازي مع بقية الأقسام، وسينفَّذ كل قسم في خيط منفصل. سيولِّد المصرِّف هذه الشيفرة لتنفيذها بالتوازي. لاحظ الفرق بين كلمة "قسم" هنا، و"أقسام" في الجزء السابق أعلاه من المثال، نتابع ...
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6216_9" style="">
<span class="pln"> </span><span class="com">#pragma</span><span class="pln"> omp section
 </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"hello "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
 </span><span class="com">/** افعل شيئا ما **/</span><span class="pln">
 </span><span class="pun">}</span><span class="pln">
 </span><span class="com">#pragma</span><span class="pln"> omp section 
 </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"world "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
   </span><span class="com">/** افعل شيئا ما **/</span><span class="pln">
 </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// لن يُنفّذ هذا السطر حتى تنتهي كل الأقسام أعلاه</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"end"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></pre>

<p>
	الخرج: هناك نتيجتان محتمَلتان يمكن أن تنتُجا عن هذا المثال، وذلك اعتمادًا على نظام التشغيل والأجهزة المستخدمة. يوضّح الخرج أيضًا مشكلة <strong>حالة التسابق</strong> (race condition problem) التي قد تحدث نتيجة لمثل هذا التقديم.
</p>

<table>
<thead><tr>
<th>
				الخرج أ
			</th>
			<th>
				الخرج ب
			</th>
		</tr></thead>
<tbody><tr>
<td>
				begin hello world end
			</td>
			<td>
				begin world hello end
			</td>
		</tr></tbody>
</table>
<h3 id="openmp-">
	OpenMP: الأقسام المتوازية
</h3>

<p>
	يوضّح هذا المثال كيفية تنفيذ أجزاء من الشيفرة بالتوازي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6216_11" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"begin "</span><span class="pun">;</span><span class="pln">
</span><span class="com">// بداية الأقسام المتوازية</span><span class="pln">
</span><span class="com">#pragma</span><span class="pln"> omp parallel sections
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// تنفيذ الأقسام بالتوازي</span><span class="pln">
    </span><span class="com">#pragma</span><span class="pln"> omp section
    </span><span class="pun">{</span><span class="pln">
    </span><span class="pun">...</span><span class="pln"> </span><span class="kwd">do</span><span class="pln"> something </span><span class="pun">...</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"hello "</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">    
    </span><span class="com">#pragma</span><span class="pln"> omp section
    </span><span class="pun">{</span><span class="pln">
    </span><span class="pun">...</span><span class="pln"> </span><span class="pun">افعل</span><span class="pln"> </span><span class="pun">شيئا</span><span class="pln"> </span><span class="pun">ما</span><span class="pln"> </span><span class="pun">...</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"world "</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="com">#pragma</span><span class="pln"> omp section
    </span><span class="pun">{</span><span class="pln">
</span><span class="pun">...</span><span class="pln"> </span><span class="pun">افعل</span><span class="pln"> </span><span class="pun">شيئا</span><span class="pln"> </span><span class="pun">ما</span><span class="pln"> </span><span class="pun">...</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"forever "</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// نهاية الأقسام</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"end"</span><span class="pun">;</span></pre>

<p>
	نظرًا لأنّ ترتيب التنفيذ غير مضمون، فقد ترى أيًّا من المخرجات التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8337_15" style="">
<span class="hljs-keyword">begin</span> hello world <span class="hljs-keyword">forever</span> <span class="hljs-keyword">end</span>
<span class="hljs-keyword">begin</span> world hello <span class="hljs-keyword">forever</span> <span class="hljs-keyword">end</span>
<span class="hljs-keyword">begin</span> hello <span class="hljs-keyword">forever</span> world <span class="hljs-keyword">end</span>
<span class="hljs-keyword">begin</span> <span class="hljs-keyword">forever</span> hello world <span class="hljs-keyword">end</span>
</pre>

<h3 id="openmp-">
	OpenMP: التوازي في الحلقات
</h3>

<p>
	يوضّح هذا المثال كيفية تقسيم حلقة إلى أجزاء متساوية وتنفيذها بشكل متوازي، سنقسم متجه العنصر إلى <code>()element.size</code> و <code>Thread Qty</code> ثم نخصص نطاق كل خيط على حدة، انظر ...
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6216_13" style="">
<span class="com">#pragma</span><span class="pln"> omp parallel </span><span class="kwd">for</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">size_t</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> element</span><span class="pun">.</span><span class="pln">size</span><span class="pun">();</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i</span><span class="pun">)</span><span class="pln">
element</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">...</span></pre>

<p>
	مثال على تخصيص 100 عنصر لكل خيط: خيط 1: 0~99. خيط 1: 100~199. خيط 1: 200~299. وهكذا .. تستمر العملية كلها عند إكمال الخيوط كلها للمهمة التي أوكلت إليها من الحلقة.
</p>

<ul>
<li>
		يرجى توخي الحذر الشديد وعدم تعديل حجم <a data-ss1615541024="1" data-ss1615541531="1" data-ss1617023041="1" href="%D8%B1%D8%A7%D8%A8%D8%B7%20%D8%A7%D9%84%D9%81%D8%B5%D9%84%2049" rel="">المتجه</a> المستخدم في حلقة for المتوازية لأنّ فهارس النطاق المُخصّص لا تُحدَّث تلقائيًا.
	</li>
</ul>
<h3 id="openmp-">
	OpenMP: التجميع / الاختزال المتوازي
</h3>

<p>
	يوضّح هذا المثال مفهوم الاختزال (reduction) أو التجميع (gathering) باستخدام المتجهات (<code>‎std::vector‎</code>) و OpenMP.
</p>

<p>
	سنفترض أنّنا نحتاج عدّة خيوط لمساعدتنا على توليد مجموعة كبيرة من الأشياء، وقد استخدمنا <code>‎int‎</code> هنا للتبسيط، بيْد أنّه يمكن استبدالها بأنواع بيانات أخرى.
</p>

<p>
	سيكون هذا مفيدًا عندما تحتاج إلى دمج نتائج من المهام الفرعية (slaves) لتجنّب أخطاء الأجزاء (segement faults)، أو انتهاكات الوصول إلى الذاكرة، وفي نفس الوقت لا ترغب في استخدام المكتبات، أو مكتبات حاويات مخصّصة للمزامنة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6216_16" style="">
<span class="com">// المتجه الرئيسي</span><span class="pln">
</span><span class="com">// نريد متجهًا يضم النتائج المجموعة من المهام الفرعية</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="typ">Master</span><span class="pun">;</span><span class="pln">

</span><span class="com">// تلميح للمصرّف لكي ينفّذ الكتلة { } بالتوازي في كل الخيوط المتاحة</span><span class="pln">
</span><span class="com">#pragma</span><span class="pln"> omp parallel </span><span class="pun">{</span><span class="pln">
    </span><span class="com">//  في هذه المنطقة، يمكنك كتابة أي شيفرة تريد لكل خيط فرعي</span><span class="pln">
    </span><span class="com">// في هذه الحالة، هي متجهة لتخزين كل نتائجها</span><span class="pln">
    </span><span class="com">// ليس علينا أن نقلق من عدد الخيوط المُنشأة أو مما إذا كنا نريد تكرار هذا التصريح هنا</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="typ">Slave</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// أخبر المصرف هنا أن يستخدم هنا كل الخيوط المخصصة لهذا الحيز المتوازي لتنفيذ هذه الحلقة على مراحل</span><span class="pln">
    </span><span class="com">// 1000000 / Thread Qty الفعلية هي الحِمل الفعلي هي </span><span class="pln">
    </span><span class="com">// المصرّفَ ألا ينتظر انتهاء جميع المهام الفرعية nowait وتخبر الكلمة المفتاحية</span><span class="pln">
</span><span class="com">#pragma</span><span class="pln"> omp </span><span class="kwd">for</span><span class="pln"> nowait
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">size_t</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">1000000</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i </span><span class="pun">{</span><span class="pln">
            </span><span class="com">/* افعل شيئا ما */</span><span class="pln">
            </span><span class="pun">....</span><span class="pln">
            </span><span class="typ">Slave</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(...);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="com">// ستنفّذ المهام الفرعية التي تنهي هذا الجزء من العمل الخيوطَ واحدًا تلو الآخر</span><span class="pln">
        </span><span class="com">// تضمن الأقسام الحرجة أنّ خيطا واحدا على الأكثر سينفِّذ الكتلة { } في كل مرة </span><span class="pln">
      </span><span class="com">#pragma</span><span class="pln"> omp critical </span><span class="pun">{</span><span class="pln">
            </span><span class="com">// دمج المهمة الفرعية مع الرئيسية.</span><span class="pln">
            </span><span class="com">// استخدم مكرِّرات النقل بدلًا من ذلك، وتجنب النسخ إلا إن كنت تريد استخدامه بعد هذا القسم.</span><span class="pln">
                   </span><span class="typ">Master</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="typ">Master</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln">
                std</span><span class="pun">::</span><span class="pln">make_move_iterator</span><span class="pun">(</span><span class="typ">Slave</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">()),</span><span class="pln">
                std</span><span class="pun">::</span><span class="pln">make_move_iterator</span><span class="pun">(</span><span class="typ">Slave</span><span class="pun">.</span><span class="pln">end</span><span class="pun">()));</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1615541024="1" data-ss1615541531="1" data-ss1617023041="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصول:
</p>

<ul>
<li>
		Chapter 80: Threading
	</li>
	<li>
		Chapter 85: Mutexes
	</li>
	<li>
		Chapter 86: Recursive Mutex
	</li>
	<li>
		Chapter 87: Semaphore
	</li>
	<li>
		Chapter 88: Futures and Promises
	</li>
	<li>
		Chapter 131: Concurrency With OpenMP
	</li>
</ul>
<p>
	من كتاب <a data-ss1615541024="1" data-ss1615541531="1" data-ss1617023041="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">972</guid><pubDate>Sat, 05 Sep 2020 18:04:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x642;&#x648;&#x627;&#x644;&#x628; Templates &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D9%82%D9%88%D8%A7%D9%84%D8%A8-templates-%D9%81%D9%8A-cpp-r971/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_08/42.png.a45094a2fa9397415a691f3ecffcd21a.png" /></p>

<p>
	صار بالإمكان قولبة الأصناف والدوالّ والمتغيّرات في لغة ++C منذ C++‎ 14، والقالب هو شيفرة لها بعض المعاملات الحرّة (free parameters) التي ستُستبدَل فيما بعد بأصناف أو دوال أو متغيّرات حقيقية عند تحديد تلك المعاملات.
</p>

<p>
	وقد تكون المعاملات أنواعًا أو قيمًا أو قوالب بحد ذاتها، ومن أمثلة القوالب: <a data-ss1617023042="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-29-%D8%A7%D9%84%D9%86%D9%88%D8%B9-stdvector-%D8%A7%D9%84%D9%85%D8%AA%D8%AC%D9%87%D8%A7%D8%AA-%D9%81%D9%8A-cpp-r941/" rel="">المتجهات</a> (<code>‎std::vector‎</code>)، التي تصبح أنواع حاويات حقيقية عند تحديد نوع العنصر، كما في <code>‎std::vector&lt;int&gt;‎</code>.
</p>

<h2>
	قالب صنف أولي Basic Class Template
</h2>

<p>
	الفكرة الأساسية لقالب الصنف هي أنّ مُعامل القالب سيُستبدَل بنوع معيّن في وقت التصريف، ونتيجة لذلك يمكن استخدام نفس الصنف مع عدّة أنواع. يحدّد المستخدمُ النوعَ الذي سيُستخدَم عند التصريح عن متغيّر من ذلك الصنف، ولدينا ثلاثة أمثلة على ذلك:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_7" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">            </span><span class="com">// صنف بسيط لاحتواء عدد من أيّ نوع</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Number</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">void</span><span class="pln"> setNum</span><span class="pun">(</span><span class="pln">T n</span><span class="pun">);</span><span class="pln">            </span><span class="com">// ضبط حقل الصنف عند العدد المُعطى</span><span class="pln">
        T plus1</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">;</span><span class="pln">            </span><span class="com">// "follower" يعيد حقل الصنف</span><span class="pln">
        </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
            T num</span><span class="pun">;</span><span class="pln">                </span><span class="com">// حقل من الصنف</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">            </span><span class="com">// ضبط حقل الصنف عند العدد المُعطى</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Number</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;::</span><span class="pln">setNum</span><span class="pun">(</span><span class="pln">T n</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        num </span><span class="pun">=</span><span class="pln"> n</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">            </span><span class="com">// "follower" إعادة</span><span class="pln">
    T </span><span class="typ">Number</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;::</span><span class="pln">plus1</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> num </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Number</span><span class="str">&lt;int&gt;</span><span class="pln"> anInt</span><span class="pun">;</span><span class="pln">            </span><span class="com">// (في الصنف T ستستبدل int) إجراء اختبار مع عدد صحيح </span><span class="pln">
    anInt</span><span class="pun">.</span><span class="pln">setNum</span><span class="pun">(</span><span class="lit">1</span><span class="pun">);</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"My integer + 1 is "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> anInt</span><span class="pun">.</span><span class="pln">plus1</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">        </span><span class="com">// 2 يطبع</span><span class="pln">

  </span><span class="typ">Number</span><span class="str">&lt;double&gt;</span><span class="pln"> aDouble</span><span class="pun">;</span><span class="pln">        </span><span class="com">// double الاختبار بعدد من النوع</span><span class="pln">
    aDouble</span><span class="pun">.</span><span class="pln">setNum</span><span class="pun">(</span><span class="lit">3.1415926535897</span><span class="pun">);</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"My double + 1 is "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> aDouble</span><span class="pun">.</span><span class="pln">plus1</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// يطبع 4.14159</span><span class="pln">

    </span><span class="typ">Number</span><span class="str">&lt;float&gt;</span><span class="pln"> aFloat</span><span class="pun">;</span><span class="pln">            </span><span class="com">// الاختبار بعدد عشري</span><span class="pln">
    aFloat</span><span class="pun">.</span><span class="pln">setNum</span><span class="pun">(</span><span class="lit">1.4</span><span class="pun">);</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"My float + 1 is "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> aFloat</span><span class="pun">.</span><span class="pln">plus1</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">        </span><span class="com">// يطبع 2.4</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">    
</span><span class="pun">}</span></pre>

<h2>
	قوالب الدوال Function Templates
</h2>

<p>
	يمكن تطبيق القولبة على الدوالّ (والهياكل التقليدية الأخرى)، انظر المثال التالي حيث تمثل <code>T</code> نوعًا مجهولًا، ويكون كلا الوسيطين من نفس النوع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_9" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> printSum</span><span class="pun">(</span><span class="pln">T add1</span><span class="pun">,</span><span class="pln"> T add2</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">add1 </span><span class="pun">+</span><span class="pln"> add2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	يمكن استخدامها بنفس الطريقة التي تستخدم بها قوالب الهياكل (structure templates).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_11" style="">
<span class="pln">printSum</span><span class="str">&lt;int&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">);</span><span class="pln">
printSum</span><span class="str">&lt;float&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="lit">4.5</span><span class="pln"> f</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8.9</span><span class="pln"> f</span><span class="pun">);</span></pre>

<p>
	يُستخدَم وسيط القالب في كلتا الحالتين لاستبدال أنواع المعاملات؛ وستعمل النتيجة بشكل مشابه لدوالّ C++‎ العادية، فإذا لم تتطابق المعاملات مع نوع القالب، فإنّ المٌصرّف سيطبّق التحويلات القياسية.
</p>

<p>
	إحدى الخصائص الإضافية لدوالّ القوالب -على عكس أصناف القوالب- هي أنّ المُصرّف يمكنه استنتاج معاملات القالب بناءً على المعاملات المُمرّرة إلى الدالّة.
</p>

<p>
	في الحالة التالية يكون كلا المعاملين من نوع <code>int</code>، وذلك يتيح للمصرف استنباط النوع، وتكون <code>T</code> مساوية لـ <code>int</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_13" style="">
<span class="pln">printSum</span><span class="pun">(</span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">);</span><span class="pln">    </span></pre>

<p>
	في هذه الحالة يكون المعاملان من نوعين مختلفين، ويعجز المصرف عن استنتاج نوع <code>T</code> بسبب وجود تناقضات، ونتيجة لهذا يحدث خطأ في التصريف.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_15" style="">
<span class="pln">printSum</span><span class="pun">(</span><span class="lit">5.0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">);</span></pre>

<p>
	تتيح لنا هذه الميزة تبسيط الشيفرة عند الجمع بين بنيات ودوالّ القالب. يوجد نمط شائع في المكتبة القياسية يسمح لنا بجعل <code>‎template structure X‎</code> تستخدم دالّة مساعدة <code>‎make_X()‎</code>. انظر المثال التالي الذي يوضح كيف يبدو نمط <code>make_X</code>:
</p>

<ol>
<li>
		هيكل قالب مع نوع قالب واحد أو أكثر:
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_17" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T1</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T2</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">MyPair</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        T1 first</span><span class="pun">;</span><span class="pln">
        T2 second</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span></pre>

<ol start="2">
<li>
		دالة <code>make</code> لها نوع لكل معاملات القوالب في هيكل القالب
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_19" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T1</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T2</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="typ">MyPair</span><span class="pun">&lt;</span><span class="pln">T1</span><span class="pun">,</span><span class="pln"> T2</span><span class="pun">&gt;</span><span class="pln"> make_MyPair</span><span class="pun">(</span><span class="pln">T1 t1</span><span class="pun">,</span><span class="pln"> T2 t2</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">MyPair</span><span class="pun">&lt;</span><span class="pln">T1</span><span class="pun">,</span><span class="pln"> T2</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> t1</span><span class="pun">,</span><span class="pln"> t2 </span><span class="pun">};</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	كيف يساعد هذا؟ انظر ما يلي حيث يكون <code>val1</code> و <code>val2</code> من نفس النوع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_21" style="">
<span class="kwd">auto</span><span class="pln"> val1 </span><span class="pun">=</span><span class="pln"> </span><span class="typ">MyPair</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">float</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8.7</span><span class="pln"> </span><span class="pun">};</span><span class="pln">   </span><span class="com">// إنشاء الكائن يعرّف الأنواع صراحة</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> val2 </span><span class="pun">=</span><span class="pln"> make_MyPair</span><span class="pun">(</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8.7</span><span class="pun">);</span><span class="pln">        </span><span class="com">// إنشاء الكائن باستخدام أنواع المعاملات</span></pre>

<p>
	<strong>ملاحظة</strong>: لم يُصمّم هذا لاختصار الشيفرة وإنّما صُمِّم لجعلها أكثر متانة إذ يسمح بتغيير الأنواع عن طريق تغيير الشيفرَة في مكان واحد وليس في مواقع متعدّدة.
</p>

<h2>
	قوالب التعبير Expression templates
</h2>

<p>
	قوالب التعابير هي تقنية تحسين (optimization) في وقت التصريف تُستخدم في الغالب في الحوسبة العلمية (scientiﬁc computing)، والغرض الرئيسي منها هو تجنّب إهدار الوقت وتحسين الحسابات باستخدام مسار واحد -عادةً عند إجراء عمليات على المجاميع العددية-.
</p>

<p>
	في البداية، تُقسَّم قوالب التعابير من أجل التحايل على الفوارق الناجمة عن التحميل الزائد عند تنفيذ أنواع المصفوفات (<code>‎Array‎</code>) أو المصفوفات المتعددة (<code>‎Matrix‎</code>).
</p>

<p>
	ويجب أن تفهم الهدف من قوالب التعبير أولًا قبل الغوص فيها، انظر الصنف Matrix الوارد في المثال أدناه:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_23" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> COL</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> ROW</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Matrix</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">using</span><span class="pln"> value_type </span><span class="pun">=</span><span class="pln"> T</span><span class="pun">;</span><span class="pln">
        </span><span class="typ">Matrix</span><span class="pun">():</span><span class="pln"> values</span><span class="pun">(</span><span class="pln">COL </span><span class="pun">*</span><span class="pln">ROW</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

        </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">size_t</span><span class="pln"> cols</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> COL</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">size_t</span><span class="pln"> rows</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> ROW</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">const</span><span class="pln"> T </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pun">()(</span><span class="typ">size_t</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> </span><span class="typ">size_t</span><span class="pln"> y</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> values</span><span class="pun">[</span><span class="pln">y </span><span class="pun">*</span><span class="pln">COL </span><span class="pun">+</span><span class="pln"> x</span><span class="pun">];</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        T </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pun">()(</span><span class="typ">size_t</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> </span><span class="typ">size_t</span><span class="pln"> y</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> values</span><span class="pun">[</span><span class="pln">y </span><span class="pun">*</span><span class="pln">COL </span><span class="pun">+</span><span class="pln"> x</span><span class="pun">];</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
            std</span><span class="pun">::</span><span class="typ">vector</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> values</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> COL</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> ROW</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="typ">Matrix</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> COL</span><span class="pun">,</span><span class="pln"> ROW</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">operator</span><span class="pun">+(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Matrix</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> COL</span><span class="pun">,</span><span class="pln"> ROW</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">lhs</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Matrix</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> COL</span><span class="pun">,</span><span class="pln"> ROW</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">rhs</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Matrix</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> COL</span><span class="pun">,</span><span class="pln"> ROW</span><span class="pun">&gt;</span><span class="pln"> result</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">size_t</span><span class="pln"> y </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> y </span><span class="pun">!=</span><span class="pln"> lhs</span><span class="pun">.</span><span class="pln">rows</span><span class="pun">();</span><span class="pln"> </span><span class="pun">++</span><span class="pln">y</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">size_t</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> x </span><span class="pun">!=</span><span class="pln"> lhs</span><span class="pun">.</span><span class="pln">cols</span><span class="pun">();</span><span class="pln"> </span><span class="pun">++</span><span class="pln">x</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                result</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> lhs</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> rhs</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> result</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	يمكنك الآن كتابة تعبيرات Matrix على النحو:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_25" style="">
<span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> cols </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2000</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> rows </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Matrix</span><span class="pun">&lt;</span><span class="kwd">double</span><span class="pun">,</span><span class="pln"> cols</span><span class="pun">,</span><span class="pln"> rows</span><span class="pun">&gt;</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> c</span><span class="pun">;</span><span class="pln">
</span><span class="com">// a, b &amp;c هيئ</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> y </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> y </span><span class="pun">!=</span><span class="pln"> rows</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">y</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> x </span><span class="pun">!=</span><span class="pln"> cols</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">x</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        a</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1.0</span><span class="pun">;</span><span class="pln">
        b</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2.0</span><span class="pun">;</span><span class="pln">
        c</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3.0</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">Matrix</span><span class="pun">&lt;</span><span class="kwd">double</span><span class="pun">,</span><span class="pln"> cols</span><span class="pun">,</span><span class="pln"> rows</span><span class="pun">&gt;</span><span class="pln"> d </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> b </span><span class="pun">+</span><span class="pln"> c</span><span class="pun">;</span><span class="pln">    </span><span class="com">// d(x, y) = 6</span></pre>

<p>
	كما هو مُوضّح أعلاه، فتستطيع توفير صيغة تحاكي الصيغة الرياضية المعتادة للمصفوفات عبر <a data-ss1617023042="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-22-%D8%A7%D9%84%D8%AA%D8%AD%D9%85%D9%8A%D9%84-%D8%A7%D9%84%D8%B2%D8%A7%D8%A6%D8%AF-overloading-%D8%AA%D8%AD%D9%84%D9%8A%D9%84%D9%87-%D9%88%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D9%87-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D9%81%D9%8A-cpp-r934/" rel="">التحميل الزائد</a> للعامل <code>‎operator+()‎</code>، لكن التنفيذ السابق غير فعّال مقارنةً بالإصدارات المكافئة "المصنوعة يدويًا".
</p>

<p>
	ولفهم السبب، عليك مراعاة ما يحدث عند كتابة تعبير مثل <code>‎Matrix d = a + b‎ + c‎</code>، يُنشر هذا التعبير في الواقع إلى التعبير <code>‎((a + b) + c)‎</code>، أو <code>‎operator+(operator+(a, b), c)‎</code>، أي تُنفّذ الحلقة الموجودة داخل <code>operator+()‎</code> مرّتين، بينما كان من الممكن إجراؤها مرّة واحدة. هذا يؤدّي أيضًا إلى إنشاء كائنين مؤقّتين، مما يضعف الأداء أكثر. ويبدو أنّ المرونة التي حصلنا عليها والناتجة عن استخدام صياغة قريبة للصياغة المعمول بها في الرياضيات كانت على حساب الأداء.
</p>

<p>
	على سبيل المثال، تستطيع تنفيذ تجميع مصفوفةٍ بأسلوب أفضل بدون التحميل الزائد للعامل، وباستخدام مسار تمرير واحد:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_27" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> COL</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> ROW</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="typ">Matrix</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> COL</span><span class="pun">,</span><span class="pln"> ROW</span><span class="pun">&gt;</span><span class="pln"> add3</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Matrix</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> COL</span><span class="pun">,</span><span class="pln"> ROW</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Matrix</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> COL</span><span class="pun">,</span><span class="pln"> ROW</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">b</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Matrix</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> COL</span><span class="pun">,</span><span class="pln"> ROW</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">c</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Matrix</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> COL</span><span class="pun">,</span><span class="pln"> ROW</span><span class="pun">&gt;</span><span class="pln"> result</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">size_t</span><span class="pln"> y </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> y </span><span class="pun">!=</span><span class="pln"> ROW</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">y</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">size_t</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> x </span><span class="pun">!=</span><span class="pln"> COL</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">x</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                result</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> a</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> c</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> result</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	لكنّ المثال السابق له عيوبه، لأنّه ينشئ واجهة أكثر تعقيدًا للصنف Matrix، إذ سيكون عليك اعتبار توابع من قبيل: <code>‎Matrix::add2()‎</code> و <code>‎Matrix::AddMultiply()‎</code>. بدلاً من ذلك، دعنا نرجع خطوة إلى الوراء ونرى كيف يمكننا تكييف التحميل الزائد للمُعامل لأجل تحسين الأداء.
</p>

<p>
	تنبع المشكلة من حقيقة أنّ التعبير <code>‎Matrix d = a + b + c‎</code> يُقيَّم قبل إنشاء شجرة التعبير بأكملها، أي ما نريده حقًا هو تقييم <code>‎a + b + c‎</code> مرّة واحدة، وفقط عندما تحتاج إلى إسناد التعبير الناتج إلى <code>‎d‎</code>.
</p>

<p>
	وتلك هي الفكرة الأساسية وراء قوالب التعبير: بدلاً من أن يُقيّم المعامل <code>‎operator+()‎</code> نتيجة إضافة نسختين من <code>Matrix</code> على الفور، فسيُعيد "قالبَ تعبير" لتقييمه مستقبلًا بعد الانتهاء من بناء شجرة التعبير بأكملها.
</p>

<p>
	على سبيل المثال، فيما يلي تنفيذ ممكن لقالب تعبير يتوافق مع جمع عنصرين من نوعين مختلفين:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_29" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> LHS</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> RHS</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MatrixSum</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">using</span><span class="pln"> value_type </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> LHS</span><span class="pun">::</span><span class="pln">value_type</span><span class="pun">;</span><span class="pln">
        </span><span class="typ">MatrixSum</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> LHS </span><span class="pun">&amp;</span><span class="pln">lhs</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> RHS </span><span class="pun">&amp;</span><span class="pln">rhs</span><span class="pun">):</span><span class="pln"> rhs</span><span class="pun">(</span><span class="pln">rhs</span><span class="pun">),</span><span class="pln"> lhs</span><span class="pun">(</span><span class="pln">lhs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

        value_type </span><span class="kwd">operator</span><span class="pun">()(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> y</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> lhs</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> rhs</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">const</span><span class="pln"> LHS </span><span class="pun">&amp;</span><span class="pln">lhs</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> RHS </span><span class="pun">&amp;</span><span class="pln">rhs</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span></pre>

<p>
	وهذه هي النسخة المُحدثة من <code>‎operator+()‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_31" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> LHS</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> RHS</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="typ">MatrixSum</span><span class="pun">&lt;</span><span class="pln">LHS</span><span class="pun">,</span><span class="pln"> RHS</span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">+(</span><span class="kwd">const</span><span class="pln"> LHS </span><span class="pun">&amp;</span><span class="pln">lhs</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> LHS </span><span class="pun">&amp;</span><span class="pln">rhs</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">MatrixSum</span><span class="pun">&lt;</span><span class="pln">LHS</span><span class="pun">,</span><span class="pln"> RHS</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">lhs</span><span class="pun">,</span><span class="pln"> rhs</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	كما ترى، لا يعيد <code>‎operator+()‎</code> "تقييمًا مُتسرّعًا" بعد الآن لنتيجَةِ إضافة نسختين من <code>Matrix</code> (والتي ستكون نسخة أخرى من <code>Matrix</code>)، ولكنه يعيد قالب تعبير يمثّل عملية الإضافة. ربما يجب أن تتذكّر أنّ التعبير لم يُقيَّم بعد، وإنما يخزّن مراجع إلى معاملاته وحسب. وفي الحقيقة، لا شيء يمنعك من إنشاء قالب تعبير <code>‎MatrixSum&lt;&gt;‎</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_33" style="">
<span class="typ">MatrixSum</span><span class="pun">&lt;</span><span class="typ">Matrix</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">double</span><span class="pun">&gt;,</span><span class="pln"> </span><span class="typ">Matrix</span><span class="str">&lt;double&gt;</span><span class="pun">&gt;</span><span class="pln"> </span><span class="typ">SumAB</span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">);</span></pre>

<p>
	يمكنك تقييم التعبير <code>‎d =‎‎a + ‎b‎</code> في مرحلة لاحقة، حين تحتاج فعليًا إلى نتيجة الجمع، كما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_35" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> y </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> y </span><span class="pun">!=</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">rows</span><span class="pun">();</span><span class="pln"> </span><span class="pun">++</span><span class="pln">y</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> x </span><span class="pun">!=</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">cols</span><span class="pun">();</span><span class="pln"> </span><span class="pun">++</span><span class="pln">x</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        d</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">SumAB</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	كما ترى، هناك فائدة أخرى من استخدام قوالب التعبير وهي أنك ستتمكّن من تقييم مجموع <code>‎a‎</code> و <code>‎b‎</code> وإسناده إلى <code>‎d‎</code> مرّة واحد. أيضًا لا شيء يمنعك من الجمع بين عدّة قوالب تعبير، فقد يُنتج <code>‎a + b + c‎</code> قالب التعبير التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_37" style="">
<span class="typ">MatrixSum</span><span class="pun">&lt;</span><span class="typ">MatrixSum</span><span class="pun">&lt;</span><span class="typ">Matrix</span><span class="str">&lt;double&gt;</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Matrix</span><span class="str">&lt;double&gt;</span><span class="pln"> </span><span class="pun">&gt;,</span><span class="pln"> </span><span class="typ">Matrix</span><span class="str">&lt;double&gt;</span><span class="pun">&gt;</span><span class="pln"> </span><span class="typ">SumABC</span><span class="pun">(</span><span class="typ">SumAB</span><span class="pun">,</span><span class="pln"> c</span><span class="pun">);</span></pre>

<p>
	وهنا، مرّة أخرى، يمكنك تقييم النتيجة النهائية مرّة واحدة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_39" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> y </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> y </span><span class="pun">!=</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">rows</span><span class="pun">();</span><span class="pln"> </span><span class="pun">++</span><span class="pln">y</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> x </span><span class="pun">!=</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">cols</span><span class="pun">();</span><span class="pln"> </span><span class="pun">++</span><span class="pln">x</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        d</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">SumABC</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	أخيرًا، آخر قطعة من اللغز هي توصيل قالب التعبير الخاص بك بالصنف <code>‎Matrix‎</code>، من خلال تنفيذ العامل <code>‎Matrix::operator=()‎</code>، الذي يأخذ قالب التعبير كوسيط ويقيِّمه في تمريرة واحدة كما فعلتَ "يدويًا" من قبل:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_41" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> COL</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> ROW</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Matrix</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">using</span><span class="pln"> value_type </span><span class="pun">=</span><span class="pln"> T</span><span class="pun">;</span><span class="pln">
        </span><span class="typ">Matrix</span><span class="pun">():</span><span class="pln"> values</span><span class="pun">(</span><span class="pln">COL </span><span class="pun">*</span><span class="pln">ROW</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

        </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">size_t</span><span class="pln"> cols</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> COL</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">size_t</span><span class="pln"> rows</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> ROW</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">const</span><span class="pln"> T </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pun">()(</span><span class="typ">size_t</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> </span><span class="typ">size_t</span><span class="pln"> y</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> values</span><span class="pun">[</span><span class="pln">y </span><span class="pun">*</span><span class="pln">COL </span><span class="pun">+</span><span class="pln"> x</span><span class="pun">];</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        T </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pun">()(</span><span class="typ">size_t</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> </span><span class="typ">size_t</span><span class="pln"> y</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> values</span><span class="pun">[</span><span class="pln">y </span><span class="pun">*</span><span class="pln">COL </span><span class="pun">+</span><span class="pln"> x</span><span class="pun">];</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> E</span><span class="pun">&gt;</span><span class="pln">
            </span><span class="typ">Matrix</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> COL</span><span class="pun">,</span><span class="pln"> ROW</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pun">=(</span><span class="kwd">const</span><span class="pln"> E </span><span class="pun">&amp;</span><span class="pln">expression</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> y </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> y </span><span class="pun">!=</span><span class="pln"> rows</span><span class="pun">();</span><span class="pln"> </span><span class="pun">++</span><span class="pln">y</span><span class="pun">)</span><span class="pln">
                </span><span class="pun">{</span><span class="pln">
                    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> x </span><span class="pun">!=</span><span class="pln"> cols</span><span class="pun">();</span><span class="pln"> </span><span class="pun">++</span><span class="pln">x</span><span class="pun">)</span><span class="pln">
                    </span><span class="pun">{</span><span class="pln">
                        values</span><span class="pun">[</span><span class="pln">y </span><span class="pun">*</span><span class="pln">COL </span><span class="pun">+</span><span class="pln"> x</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> expression</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">);</span><span class="pln">
                    </span><span class="pun">}</span><span class="pln">
                </span><span class="pun">}</span><span class="pln">

                </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
            std</span><span class="pun">::</span><span class="typ">vector</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> values</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span></pre>

<h2>
	هياكل بيانات قالب متغاير
</h2>

<p>
	<strong>الإصدار ≥ C++‎ 14</strong>
</p>

<p>
	من المفيد أحيانًا تعريف أصناف أو بنيات متغايرة لا يُعرَّف عدد حقولها وأنواعها إلا في وقت التصريف، ويُعدُّ <code>‎std::tuple‎</code> أحد الأمثلة الأساسية على ذلك، لكن قد تحتاج أحيانًا إلى تعريف هياكلك المخصّصة. انظر المثال التالي الذي يعرّف بنية باستخدام التركيب (compounding) بدلاً من الوراثة كما هو الحال في <code>‎std::tuple‎</code>.
</p>

<p>
	سنبدأ بالتعريف العام (الفارغ)، والذي يمكن أن ينفع أيضًا كحالة أوّلية (base-case) لإنهاء التكرارية في التخصيص اللاحق:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_43" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pun">...</span><span class="pln">T </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">DataStructure</span><span class="pln"> </span><span class="pun">{};</span></pre>

<p>
	يسمح لنا هذا بتعريف بنية فارغة <code>‎DataStructure&lt;&gt; data‎</code>، ولكنّ هذا غير مفيد حاليًا. بعد ذلك يأتي تخصيص الحالة التكرارية (recursive case specialisation):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_45" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pun">...</span><span class="typ">Rest</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">DataStructure</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Rest</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">DataStructure</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> T </span><span class="pun">&amp;</span><span class="pln">first</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Rest</span><span class="pln"> </span><span class="pun">&amp;...</span><span class="pln">rest</span><span class="pun">):</span><span class="pln"> first</span><span class="pun">(</span><span class="pln">first</span><span class="pun">),</span><span class="pln"> rest</span><span class="pun">(</span><span class="pln">rest</span><span class="pun">...)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

        T first</span><span class="pun">;</span><span class="pln">
        </span><span class="typ">DataStructure</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Rest</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> rest</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span></pre>

<p>
	أصبح المثال مناسبًا الآن لإنشاء هياكل بيانات عشوائية، مثل <code>&lt;DataStructure&lt;int, float, std::string‎</code>، و<code>("data(1, 2.1, "hello</code>.
</p>

<p>
	لاحظ أنّ هذا التخصيص يتطّلب وجود مُعامل قالب واحد على الأقل -وهو <code>‎T‎</code> أعلاه- دون إعارة اهتمام لخصوصيات الحُزمة <code>‎Rest‎</code>، ويسمح إدراك وجود <code>‎T‎</code> بتعريف حقل <code>‎first‎</code>. وتُحزَم بقية البيانات ذاتيًا على شكل <code>‎DataStructure‎</code> &lt;<code>‎Rest ...‎</code>&gt; <code>‎rest‎</code>، ويهيّئ المنشئ كلا العُضوَين مع استدعاء مُنشئ ذاتي على العضو <code>‎rest‎</code>.
</p>

<p>
	لفهم هذا بشكل أفضل، إليك المثال التالي: لنفترض أنّ لديك تصريحًا <code>&lt;‎DataStructure&lt;int,‎ ‎float‎</code>. في البداية يتطابق التصريح مع التخصيص، وذلك يؤدّي إلى بنية تحتوي الحقلين<code>int first</code> و <code>DataStructure&lt;float&gt; rest</code>. ويتطابق التعريف <code>‎rest‎</code> مرّة أخرى مع التخصيص إذ يُنشئ حقلين <code>float first</code> و <code>DataStructure&lt;&gt; rest</code> خاصّين به. أخيرًا، يُطابَق <code>rest</code> مع الحالة الأساسية (base-case)، ممّا ينتج عنه بنية فارغة.
</p>

<p>
	يمكنك تصور هذا على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_47" style="">
<span class="typ">DataStructure</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">float</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">-</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> first 
</span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">DataStructure</span><span class="str">&lt;float&gt;</span><span class="pln"> rest 
            </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">float</span><span class="pln"> first 
           </span><span class="pun">-</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="typ">DataStructure</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> rest 
                </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">empty</span><span class="pun">)</span></pre>

<p>
	أصبح لدينا الآن بنية بيانات، ولكنّها ليست مفيدة حاليًا، إذ لا يمكننا الوصول بسهولة إلى العناصر الفردية للبيانات. على سبيل المثال، سيتعيّن علينا استخدام <code>‎data.rest.rest.first‎</code> للوصول إلى العضو الأخير في <code>‎DataStructure&lt;int, float, std::string&gt; data‎</code>، وذلك صعب، لذا سنضيف تابع <code>‎get‎</code> إليها -مطلوب فقط في التخصيص، لأنّ بنية الحالة الأساسية لا تحتوي على بيانات أصلًا-:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_49" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pun">...</span><span class="typ">Rest</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">DataStructure</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Rest</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="pun">...</span><span class="pln">
        </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">size_t</span><span class="pln"> idx</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">auto</span><span class="pln"> get</span><span class="pun">()</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">GetHelper</span><span class="pun">&lt;</span><span class="pln">idx</span><span class="pun">,</span><span class="pln"> </span><span class="typ">DataStructure</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Rest</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;&gt;::</span><span class="pln">get</span><span class="pun">(*</span><span class="kwd">this</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">

            </span><span class="pun">...</span><span class="pln">
    </span><span class="pun">};</span></pre>

<p>
	كما ترى، فإنّ التابع <code>‎get‎</code> نفسه مُقولَب -هذه المرّة على فهرس العضو المطلوب (لذلك يمكن استخدامه على النحو <code>‎data.get&lt;1&gt;()‎</code>، على غرار الصفوف <code>‎std::tuple‎</code>-، ويتم العمل الفعلي بفضل دالّة ساكنة في الصنف المساعد <code>‎GetHelper‎</code>.
</p>

<p>
	السبب في أنّنا لم نتمكن من تعريف الدالّة المطلوبة مباشرة في التابع <code>‎get‎</code> الخاص بـ <code>‎DataStructure‎</code> هو أنّنا (كما سنرى قريبًا) نحتاج إلى تخصيص <code>‎idx‎</code>، وهذا مستحيل لأنّه لا يمكن تخصيص تابع القالب دون تخصيص قالب الصنف الحاوي. لاحظ أيضًا أنّ استخدام <code>‎auto‎</code> من نمط C++14 بسّط عملنا كثيرًا، إذ بدونها سيكون تعبير نوع القيمة المُعادة معقدًا.
</p>

<p>
	سنحتاج إلى تصريح مُسبق فارغ وتَخصيصَين في الصنف المساعد.
</p>

<p>
	أولا التصريح:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_51" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">size_t</span><span class="pln"> idx</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">GetHelper</span><span class="pun">;</span></pre>

<p>
	في الحالة الأساسية (<code>‎idx==‎</code> <code>‎0‎</code>)، سنعيد العضو <code>‎first‎</code> فقط:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_53" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pun">...</span><span class="typ">Rest</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">GetHelper</span><span class="pun">&lt;</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="typ">DataStructure</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Rest</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;&gt;</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">static</span><span class="pln"> T get</span><span class="pun">(</span><span class="typ">DataStructure</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Rest</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">data</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> data</span><span class="pun">.</span><span class="pln">first</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span></pre>

<p>
	في حالة التكرارية، سنُنقِص قيمة <code>‎idx‎</code> ونستدعي <code>‎GetHelper‎</code>على العضو <code>‎rest‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_55" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">size_t</span><span class="pln"> idx</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pun">...</span><span class="typ">Rest</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">GetHelper</span><span class="pun">&lt;</span><span class="pln">idx</span><span class="pun">,</span><span class="pln"> </span><span class="typ">DataStructure</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Rest</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;&gt;</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> get</span><span class="pun">(</span><span class="typ">DataStructure</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Rest</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">data</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">GetHelper</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> idx </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="typ">DataStructure</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Rest</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;&gt;::</span><span class="pln">get</span><span class="pun">(</span><span class="pln">data</span><span class="pun">.</span><span class="pln">rest</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span></pre>

<p>
	لنفترض أنّ لدينا <code>‎DataStructure&lt;int, float&gt; data‎</code> ونحتاج إلى <code>‎data.get&lt;1&gt;()‎</code>، هذا سيَستدعي <code>‎GetHelper&lt;1, DataStructure&lt;int, float&gt;&gt;::get(data)‎</code> (التخصيص الثاني)، والذي سيستدعي بدوره <code>‎‎GetHelper&lt;0, DataStructure&lt;float&gt;&gt;::get(data.rest)‎</code>، والتي تُعيد في النهاية (بحسب التخصيص الأوّل، إذ أنّ <code>‎idx‎</code> تساوي الآن 0) <code>‎data.rest.first‎</code>.
</p>

<p>
	هذا كل شيء! في ما يلي الشيفرة الكاملة، مع مثال توضيحي في الدالة <code>‎main‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_57" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">size_t</span><span class="pln"> idx</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">GetHelper</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pun">...</span><span class="pln">T </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">DataStructure</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pun">...</span><span class="typ">Rest</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">DataStructure</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Rest</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">DataStructure</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> T </span><span class="pun">&amp;</span><span class="pln">first</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Rest</span><span class="pln"> </span><span class="pun">&amp;...</span><span class="pln">rest</span><span class="pun">):</span><span class="pln"> first</span><span class="pun">(</span><span class="pln">first</span><span class="pun">),</span><span class="pln"> rest</span><span class="pun">(</span><span class="pln">rest</span><span class="pun">...)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

        T first</span><span class="pun">;</span><span class="pln">
        </span><span class="typ">DataStructure</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Rest</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> rest</span><span class="pun">;</span><span class="pln">

        </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">size_t</span><span class="pln"> idx</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">auto</span><span class="pln"> get</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">GetHelper</span><span class="pun">&lt;</span><span class="pln">idx</span><span class="pun">,</span><span class="pln"> </span><span class="typ">DataStructure</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Rest</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;&gt;::</span><span class="pln">get</span><span class="pun">(*</span><span class="kwd">this</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pun">...</span><span class="typ">Rest</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">GetHelper</span><span class="pun">&lt;</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="typ">DataStructure</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Rest</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;&gt;</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">static</span><span class="pln"> T get</span><span class="pun">(</span><span class="typ">DataStructure</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Rest</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">data</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> data</span><span class="pun">.</span><span class="pln">first</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">size_t</span><span class="pln"> idx</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pun">...</span><span class="typ">Rest</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">GetHelper</span><span class="pun">&lt;</span><span class="pln">idx</span><span class="pun">,</span><span class="pln"> </span><span class="typ">DataStructure</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Rest</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;&gt;</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> get</span><span class="pun">(</span><span class="typ">DataStructure</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Rest</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">data</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">GetHelper</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> idx </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="typ">DataStructure</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Rest</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;&gt;::</span><span class="pln">get</span><span class="pun">(</span><span class="pln">data</span><span class="pun">.</span><span class="pln">rest</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">DataStructure</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">float</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&gt;</span><span class="pln"> data</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2.1</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Hello"</span><span class="pun">);</span><span class="pln">

    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> data</span><span class="pun">.</span><span class="pln">get</span><span class="pun">&lt;</span><span class="lit">0</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> data</span><span class="pun">.</span><span class="pln">get</span><span class="pun">&lt;</span><span class="lit">1</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> data</span><span class="pun">.</span><span class="pln">get</span><span class="pun">&lt;</span><span class="lit">2</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	إعادة توجيه الوسائط
</h2>

<p>
	يمكن أن يقبل القالبُ المراجعَ اليمينية (rvalue references) واليسارية (lvalue references) على السواء باستخدام مرجع إعادة توجيه (forwarding reference):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_59" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">T </span><span class="pun">&amp;&amp;</span><span class="pln"> t</span><span class="pun">);</span></pre>

<p>
	في هذه الحالة، سيُستنبَط النوع الحقيقي لـ <code>‎t‎</code> من السياق:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_61" style="">
<span class="kwd">struct</span><span class="pln"> X </span><span class="pun">{};</span><span class="pln">
X x</span><span class="pun">;</span><span class="pln">
f</span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span><span class="pln">    </span><span class="com">// f&lt;X&amp;&gt;(x) تستدعي</span><span class="pln">
f</span><span class="pun">(</span><span class="pln">X</span><span class="pun">());</span><span class="pln">    </span><span class="com">// f &lt; X&gt;(x) تستدعي</span></pre>

<p>
	في الحالة الأولى، يُستنتَج النوع <code>‎T‎</code> كمرجع إلى X ‏(<code>‎X&amp;‎</code>)، أما نوع <code>‎t‎</code> فهو مرجع يساري إلى <code>X</code>، بينما في الحالة الثانية يُستنتَج نوع <code>‎T‎</code> كـ <code>‎X‎</code>، ونوع <code>‎t‎</code> كمرجع يميني إلى <code>X</code> ‏(<code>‎X&amp;&amp;‎</code>).
</p>

<p>
	<strong>ملاحظة</strong>: تجدر الإشارة إلى أنّه في الحالة الأولى، يكون <code>‎decltype(t)‎</code> و <code>‎T‎</code> متكافئان، وذلك على خلاف الحالة الثانية. ولأجل إعادة توجيه (forward)‏ <code>‎t‎</code> إلى دالّة أخرى بالشكل الصحيح، سواء كان مرجعًا يمينيا أو يساريا، فينبغي استخدام <code>std::forward</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_63" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">T </span><span class="pun">&amp;&amp;</span><span class="pln"> t</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        g</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">t</span><span class="pun">));</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	يمكن استخدام "إعادة توجيه المراجع" (Forwarding references) مع القوالب المتغايرة (variadic templates):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_65" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pun">...</span><span class="typ">Args</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">Args</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">...</span><span class="pln">args</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        g</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="typ">Args</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">args</span><span class="pun">)...);</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	<strong>ملاحظة</strong>: لا يمكن استخدام إعادة توجيه المراجع إلا مع معاملات القوالب، مثلًا في الشيفرة التالية، <code>‎v‎</code> هي مرجع يميني، وليست مرجع إعادة توجيه:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_67" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;vector&gt;</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> v</span><span class="pun">);</span></pre>

<h2>
	التخصيص الجزئي للقوالب
</h2>

<p>
	على النقيض من التخصيص الكامل للقوالب، يسمح التخصيص الجزئي للقوالب بتقديم قالب مع بعض الوسائط الخاصّة بقالب آخر ثابت. ولا يُتاح التخصيص الجزئي للقوالب إلّا لأصناف وبنيات القالب:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_69" style="">
<span class="com">// حالة شائعة</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> U</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> S
    </span><span class="pun">{</span><span class="pln">
        T t_val</span><span class="pun">;</span><span class="pln">
        U u_val</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="com">// int  حالة خاصة حيث معامل القالب الأول مثبّت عند النوع</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> V</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> S</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> V</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">double</span><span class="pln"> another_value</span><span class="pun">;</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> foo</span><span class="pun">(</span><span class="kwd">double</span><span class="pln"> arg</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="com">// افعل شيئا ما }</span><span class="pln">
        </span><span class="pun">};</span></pre>

<p>
	كما هو مُوضّح أعلاه، قد تُقدِّم التخصيصات الجزئية للقوالب مجموعات مختلفة تمامًا من البيانات والدوالّ العضوية. عند استنساخ قالب مخصّص جزئيًا، فسيتمّ اختيار التخصيص الأنسب، مثلًا لنعرّف قالبًا مع تخصيصَين جزئِيين:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_71" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> U</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> V</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> S
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"General case\n"</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> U</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> V</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> S</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> U</span><span class="pun">,</span><span class="pln"> V</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"T = int\n"</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> V</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> S</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">double</span><span class="pun">,</span><span class="pln"> V</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"T = int, U = double\n"</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span></pre>

<p>
	الاستدعاءات التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_73" style="">
<span class="pln">S</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">double</span><span class="pun">&gt;::</span><span class="pln">foo</span><span class="pun">();</span><span class="pln">
S</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">float</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&gt;::</span><span class="pln">foo</span><span class="pun">();</span><span class="pln">
S</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">double</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&gt;::</span><span class="pln">foo</span><span class="pun">();</span></pre>

<p>
	سوف تَطبع الخرج التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_75" style="">
<span class="typ">General</span><span class="pln">
</span><span class="kwd">case</span><span class="pln">
T </span><span class="pun">=</span><span class="pln"> </span><span class="typ">int</span><span class="pln">
T </span><span class="pun">=</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> U </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">double</span></pre>

<p>
	لا يمُكن أن تُخصّص قوالب الدوالّ جزئيًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_77" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> U</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">(</span><span class="pln">T t</span><span class="pun">,</span><span class="pln"> U u</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"General case: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> t </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> u </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="com">// حسنا</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a1</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> a2</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Two ints: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> a1 </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> a2 </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> invoke_foo</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    foo</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2.1</span><span class="pun">);</span><span class="pln">    </span><span class="com">// ==&gt; "General case: 1 2.1" </span><span class="pln">
    foo</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">);</span><span class="pln">    </span><span class="com">// =&gt;&gt; "Two ints: 1 2" }</span><span class="pln">

</span><span class="com">// Compilation error: partial function specialization is not allowed.</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> U</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> U</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string t</span><span class="pun">,</span><span class="pln"> U u</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"General case: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> t </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> u </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span></pre>

<h2>
	تخصيص القوالب Template Specialization
</h2>

<p>
	يمكنك تنفيذ نُسخ مُحدّدة من صنف أو تابع قالب. على سبيل المثال، إذا كان لديك:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_79" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    T sqrt</span><span class="pun">(</span><span class="pln">T t</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln"> </span><span class="com">/*Some generic implementation */</span><span class="pln"> </span><span class="pun">}</span></pre>

<p>
	فيمكنك إذن كتابة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_81" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> sqrt</span><span class="str">&lt;int&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln"> </span><span class="com">/* تنفيذ مُحسَّن للأعداد الصحيحة */</span><span class="pln"> </span><span class="pun">}</span></pre>

<p>
	سيحصل المستخدم الذي يكتُب <code>‎sqrt(4.0)‎</code> على التنفيذ العام، بينما يحصل من يكتب <code>‎sqrt(4)‎</code> على التنفيذ المُخصّص.
</p>

<h2>
	كنى القوالب Alias templates
</h2>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	انظر المثال البسيط التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_83" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">using</span><span class="pln"> pointer </span><span class="pun">=</span><span class="pln"> T </span><span class="pun">*;</span></pre>

<p>
	هذا التعريف يجعل <code>‎pointer&lt;T&gt;‎</code> كُنيةً (alias) لـ <code>‎T*‎</code>. مثلًا، يكافئ السطر التالي <code>;int* p = new int</code>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_85" style="">
<span class="pln">pointer</span><span class="str">&lt;int&gt;</span><span class="pln"> p </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">int</span><span class="pun">;</span><span class="pln"> </span></pre>

<p>
	لا يمكن تخصيص كُنى القوالب، لكن يمكن جعلها تشير إلى نوع مُتشعِّب في بنية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_87" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> nonconst_pointer_helper
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">typedef</span><span class="pln"> T </span><span class="pun">*</span><span class="pln"> type</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> nonconst_pointer_helper </span><span class="pun">&lt;</span><span class="pln"> T
</span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">typedef</span><span class="pln"> T </span><span class="pun">*</span><span class="pln"> type</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">using</span><span class="pln"> nonconst_pointer </span><span class="pun">=</span><span class="pln"> nonconst_pointer_helper</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;::</span><span class="pln">type</span><span class="pun">;</span></pre>

<h2>
	الاستنساخ الصريح
</h2>

<p>
	سيؤدي تعريف الاستنساخ الصريح إلى إنشاء صنف أو دالة أو متغيّر حقيقي من القالب، كما سيُصرّح عنه قبل استخدامه. يمكن الإشارة إلى تلك النُسخة من وحدات الترجمة الأخرى، ويمكن استخدام ذلك لتجنّب تعريف قالب في <a data-ss1617023042="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-27-%D9%85%D9%84%D9%81%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D8%B1%D9%88%D9%8A%D8%B3%D8%A7%D8%AA-header-files-%D9%88%D9%85%D8%B9%D8%A7%D9%84%D8%AC%D8%A9-%D8%A7%D9%84%D8%AA%D8%A7%D8%B1%D9%8A%D8%AE-%D9%88%D8%A7%D9%84%D9%88%D9%82%D8%AA-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D8%AA%D8%B1%D9%88%D9%8A%D8%B3%D8%A9-%D9%81%D9%8A-cpp-r939/" rel="">ترويسة</a> الملف إذا كان سيُستنُسخ مع مجموعة محدودة من الوسائط. مثلا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_89" style="">
<span class="com">// print_string.h</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> print_string</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> T </span><span class="pun">*</span><span class="pln">str</span><span class="pun">);</span><span class="pln">
</span><span class="com">// print_string.cpp</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">"print_string.h"</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> print_string</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">*);</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> print_string</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">wchar_t</span><span class="pln"> </span><span class="pun">*);</span></pre>

<p>
	ونظرًالأنّ <code>‎print_string&lt;char&gt;‎</code> و <code>‎print_string&lt;wchar_t&gt;‎</code> مُستنسختان بشكل صريح في <code>‎print_string.cpp‎</code>، فسيتمكّن الرابط (linker) من العثور عليهما رغم أنّ القالب <code>‎print_string‎</code> لم يُعرَّف في الترويسة، وإذا لم تكن هذه التصريحات الفورية حاضرة، فمن المحتمل حدوث خطأ في الرابط.
</p>

<p>
	<a data-ss1617023042="1" href="https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file" rel="external nofollow">تبيّن هذه الصفحة الأجنبية لماذا لا يمكن تقديم القوالب إلا في الترويسة</a>.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	إذا سُبِق تعريف الاستنساخ الصريح بالكلمة <code>‎extern‎</code>، فسيتحوّل إلى تصريح عن استنساخ صريح.
</p>

<p>
	التصريح عن استنساخ صريح لتخصيص معيّن يمنع الاستنساخ الضمني لذلك التخصيص داخل وحدة الترجمة الحالية، لكن لا مانع أن يشير مرجع لذلك التخصيص -الذي كان من الممكن أن يتسبب في استنساخ ضمني- إلى تعريف استنساخ صريح في نفس وحدة الترجمة أو في غيرها.
</p>

<p>
	<code>foo.h‎</code>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_91" style="">
<span class="com">#</span><span class="pln">
ifndef FOO_H
</span><span class="com">#define</span><span class="pln"> FOO_H
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">(</span><span class="pln">T x</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// تنفيذ معقّد</span><span class="pln">
</span><span class="pun">}#</span><span class="pln">
endif</span></pre>

<p>
	<code>foo.cpp</code>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_95" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">"foo.h"</span><span class="pln">
    </span><span class="com">// تعريف صريح لاستنساخ الحالات الشائعة.</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">(</span><span class="typ">int</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">(</span><span class="kwd">double</span><span class="pun">);</span></pre>

<p>
	<code>main.cpp</code>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_97" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">"foo.h"</span><span class="pln">
    </span><span class="com">// لها تعريف استنساخ صريح foo.cpp نعلم أنّ</span><span class="pln">
</span><span class="kwd">extern</span><span class="pln"> </span><span class="kwd">template</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">(</span><span class="kwd">double</span><span class="pun">);</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span></pre>

<p>
	هنا تُستنسخ <code>&lt;foo&lt;int</code>، وذلك لا فائدة منه بما أن <code>foo.cpp</code> تقدم استنساخًا صريحًا سلفًا، نتابع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_99" style="">
<span class="pln">    foo</span><span class="pun">(</span><span class="lit">42</span><span class="pun">);</span></pre>

<p>
	وهنا، لن تُستنسخ <code>&lt;foo&lt;double</code> إذ تستخدم نسخة من <code>&lt;foo&lt;double</code> في <code>foo.cpp</code> بدلًا من ذلك، انظر بقية المثال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_101" style="">
<span class="pln">    foo</span><span class="pun">(</span><span class="lit">3.14</span><span class="pun">);</span><span class="pln">   
</span><span class="pun">}</span></pre>

<h2>
	مُعامل قالب غير نوعي
</h2>

<p>
	يُسمح لنا بالتصريح عن قيم التعبيرات الثابتة التي تفي بأحد المعايير التالية، وذلك خلا النوع كمعامِل قالب:
</p>

<ul>
<li>
		نوع عددي صحيح أو تعداد (enumeration).
	</li>
	<li>
		مؤشّر إلى كائن أو مؤشّر إلى دالة.
	</li>
	<li>
		مرجع يساري إلى كائن أو مرجع يميني إلى دالّة.
	</li>
	<li>
		مؤشّر إلى عضو.
	</li>
	<li>
		<code>std::nullptr_t</code>.
	</li>
</ul>
<p>
	يمكن تحديد معاملات القالب غير النوعية بشكل صريح -مثل كل معاملات القوالب- أو اشتقاقها أو تحديد قيمها الافتراضية ضمنيًا عبر استنباط وسيط القالب. هذا مثال على استخدام مُعامل قالب غير نوعي، إذ سنمرر مصفوفة بالمرجع تتطلب حجمًا معينًا، ونحن نسمح بكل الأحجام باستخدام قالب <code>size</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_103" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> size</span><span class="pun">&gt;</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> size_of</span><span class="pun">(</span><span class="pln">T</span><span class="pun">(&amp;</span><span class="pln">anArray</span><span class="pun">)[</span><span class="pln">size</span><span class="pun">])</span><span class="pln">  
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> size</span><span class="pun">;</span><span class="pln">   
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">char</span><span class="pln"> anArrayOfChar</span><span class="pun">[</span><span class="lit">15</span><span class="pun">];</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"anArrayOfChar: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> size_of</span><span class="pun">(</span><span class="pln">anArrayOfChar</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> anArrayOfData</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"anArrayOfData: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> size_of</span><span class="pun">(</span><span class="pln">anArrayOfData</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	انظر المثال التالي على استخدام معاملات القالب النوعية وغير النوعية بشكل صريح، إذ يكون <code>int</code> معامِلًا نوعيًا، أما 5 فلا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_105" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;array&gt;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">array</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">&gt;</span><span class="pln"> foo</span><span class="pun">;</span><span class="pln"> 
</span><span class="pun">}</span></pre>

<p>
	تعدّ معاملات القوالب غير النوعية إحدى طرق تحقيق عوديّة القوالب والبرمجة العليا.
</p>

<h2>
	التصريح عن وسائط القوالب غير النوعية عبر auto
</h2>

<p>
	كان عليك قبل الإصدار C++‎ 17 أن تحدد نوع معامِل القالب غير النوعي عند كتابته، لذلك كان من الشائع كتابة شيء من هذا القبيل:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_107" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> T N</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> integral_constant
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> type </span><span class="pun">=</span><span class="pln"> T</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">constexpr</span><span class="pln"> T value </span><span class="pun">=</span><span class="pln"> N</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> five </span><span class="pun">=</span><span class="pln"> integral_constant</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">;</span></pre>

<p>
	ولكن بالنسبة للتعبيرات المعقّدة، فإنّ استخدام الصيغة أعلاه يتطّلب كتابة <code>‎decltype(expr), expr‎</code> عند استنساخ القوالب، والحلّ هو تبسيط هذا المنظور واستخدام <code>‎auto‎</code>:
</p>

<p>
	<strong>الإصدار ≥ C++‎ 17</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_109" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> N</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> integral_constant
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> type </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">N</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">constexpr</span><span class="pln"> type value </span><span class="pun">=</span><span class="pln"> N</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> five </span><span class="pun">=</span><span class="pln"> integral_constant</span><span class="pun">&lt;</span><span class="lit">5</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">;</span></pre>

<h3>
	حاذف مخصّص للمؤشرات الحصرية unique_ptr
</h3>

<p>
	من أمثلة استخدام وسائط القوالب غير النوعية هي الجمع بين تحسين الأساس الفارغ وحاذف مُخصَّص للمؤشّرات الحصرية <code>‎unique_ptr‎</code>. وتختلف حاذفات الواجهات البرمجية للغة C في نوع القيمة المعادة، ولكن هذا لا يشغلنا، فكل ما نريد هو شيء يعمل مع كل الدوالّ:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_111" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> </span><span class="typ">DeleteFn</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">FunctionDeleter</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
            </span><span class="kwd">void</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">()(</span><span class="pln">T </span><span class="pun">*</span><span class="pln">ptr</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="typ">DeleteFn</span><span class="pun">(</span><span class="pln">ptr</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> </span><span class="typ">DeleteFn</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> unique_ptr_deleter </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">unique_ptr</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> </span><span class="typ">FunctionDeleter</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">DeleteFn</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="pun">;</span></pre>

<p>
	والآن يمكنك استخدام أيّ مؤشّر دالة يقبل وسيطًا من النوع <code>‎T‎</code> كمُعامل قالب غير نوعي، بصرف النظر عن نوع القيمة المُعادة، ودون القلق من أيّ حِمل إضافي في الحجم:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_113" style="">
<span class="pln">unique_ptr_deleter</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="typ">FILE</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">fclose </span><span class="pun">&gt;</span><span class="pln"> p</span><span class="pun">;</span></pre>

<h2>
	معامِلات قالب القالب
</h2>

<p>
	قد نود أحيانًا أن نمرّر إلى القالب نوعَ قالبٍ دون تحديد قيمه، وهنا يأتي دور معاملات قالب القالب. هذا مثال بسيط يوضّح مفهوم مُعاملات قالب القالب:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_115" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Tag1</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Tag2</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">template</span><span class="str">&lt;class&gt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Tag</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">IntTag</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">typedef</span><span class="pln"> </span><span class="typ">Tag</span><span class="str">&lt;int&gt;</span><span class="pln"> type</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">IntTag</span><span class="pun">&lt;</span><span class="typ">Tag1</span><span class="pun">&gt;::</span><span class="pln">type t</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_117" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;vector&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> C</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> U </span><span class="pun">&gt;</span><span class="pln">
    C</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> cast_all</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> C</span><span class="pun">&lt;</span><span class="pln">U</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">c</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        C</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> result</span><span class="pun">(</span><span class="pln">c</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> c</span><span class="pun">.</span><span class="pln">end</span><span class="pun">());</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> result</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;float&gt;</span><span class="pln"> vf </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="lit">1.2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2.6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3.7</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> vi </span><span class="pun">=</span><span class="pln"> cast_all</span><span class="str">&lt;int&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">vf</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> i</span><span class="pun">:</span><span class="pln"> vi</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> i </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	القيم الافتراضية لمُعاملات القالب
</h3>

<p>
	كما في حالة وسائط الدوال، يمكن أن يكون لمعاملات القالب قيمٌ افتراضية، ويجب التصريح عن معاملات القالب ذات القيمة الافتراضية في نهاية قائمة معاملات القالب، والهدف هو إتاحة حذف معاملات القالب ذات القيمة الافتراضية أثناء استنساخ القالب.
</p>

<p>
	هذا مثال بسيط يوضّح كيفية استخدام القيمة الافتراضية لمُعامل القالب:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_119" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="typ">size_t</span><span class="pln"> N </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> my_array
    </span><span class="pun">{</span><span class="pln">
        T arr</span><span class="pun">[</span><span class="pln">N</span><span class="pun">];</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">/* N = 5 إهمال قيمة المعامل الافتراضية */</span><span class="pln">
    my_array</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">&gt;</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">

  </span><span class="com">/* 5 - a.arr اطبع طول */</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">a</span><span class="pun">.</span><span class="pln">arr</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="typ">int</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">

    </span><span class="com">/* N = 10 المعامل الأخير محذوف */</span><span class="pln">
    my_array</span><span class="str">&lt;int&gt;</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">

    </span><span class="com">/* 10 - a.arr  اطبع طول*/</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">b</span><span class="pun">.</span><span class="pln">arr</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="typ">int</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	أنماط القوالب عجيبة التكرار CRTP
</h2>

<p>
	أنماط القوالب عجيبة التكرار (Curiously Recurring Template Pattern)، أو CRTP اختصارًا، هي أنماط برمجية يكون من الممكن فيها أن يرث صنف من قالب صنف، بحيث يكون ذلك الصنف نفسه أحد معامِلات القالب. وتُستخدم CRTP عادة لتوفير <a data-ss1617023042="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-16-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-%D8%A7%D9%84%D8%AA%D8%B9%D8%AF%D8%AF%D9%8A%D8%A9-%D8%A7%D9%84%D8%B4%D9%83%D9%84%D9%8A%D8%A9-polymorphism-%D9%81%D9%8A-cpp-r900/" rel="">تعددية الأشكال</a> الساكنة (static polymorphism) في C++‎.
</p>

<p>
	وتُعدّ CRTP بديلًا ممتازًا وساكنًا (static) للدوالّ الوهمية والوراثة التقليدية، إذ يمكن استخدامها لتحديد خصائص الأنواع في وقت التصريف، ويقوم مبدأ عملها على جعل قالب صنف أساسي (base class template) يأخذ صنفًا مشتقًا منه كأحد معاملات القالب خاصته، وهذا يسمح بإجراء تحويل ساكن <code>‎static_cast‎</code> للمؤشّر <code>‎this‎</code> الخاص بالصنف الأساسي لكي يشير إلى الصنف المشتق.
</p>

<p>
	بالطبع، هذا يعني أنّه سيتوجّب استخدام صنف CRTP دائمًا كصنف أساسي (base class) لصنف آخر، ويجب أن يمرِّر الصنف المشتق نفسه إلى الصنف الأساسي.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 14</strong>
</p>

<p>
	لنفترض أنّ لديك مجموعة من الحاويات التي تدعم الدالّتين <code>‎begin()‎</code> و <code>‎end()‎</code>، وتتطّلب المكتبة القياسية للحاويات المزيد من الدوالّ. يمكننا هنا أن نصمم صنف CRTP أساسي يوفّر مثل تلك الدولب استنادًا إلى <code>‎begin()‎</code> و <code>‎end()‎</code> فقط:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_121" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iterator&gt;</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">Sub</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Container</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">private</span><span class="pun">:</span></pre>

<p>
	تعيد <code>()self</code> مرجعًا إلى النوع المشتق، نتابع المثال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_123" style="">
<span class="pln">            </span><span class="typ">Sub</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">self</span><span class="pun">()</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="typ">Sub</span><span class="pun">*&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">this</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">

        </span><span class="typ">Sub</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">self</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Sub</span><span class="pln">
            </span><span class="kwd">const</span><span class="pun">*&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">this</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">decltype</span><span class="pun">(</span><span class="kwd">auto</span><span class="pun">)</span><span class="pln"> front</span><span class="pun">()</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">return</span><span class="pun">*</span><span class="pln"> self</span><span class="pun">().</span><span class="pln">begin</span><span class="pun">();</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">decltype</span><span class="pun">(</span><span class="kwd">auto</span><span class="pun">)</span><span class="pln"> back</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="pln">std</span><span class="pun">::</span><span class="pln">prev</span><span class="pun">(</span><span class="pln">self</span><span class="pun">().</span><span class="pln">end</span><span class="pun">());</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">decltype</span><span class="pun">(</span><span class="kwd">auto</span><span class="pun">)</span><span class="pln"> size</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">distance</span><span class="pun">(</span><span class="pln">self</span><span class="pun">().</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> self</span><span class="pun">().</span><span class="pln">end</span><span class="pun">());</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">decltype</span><span class="pun">(</span><span class="kwd">auto</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">[](</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> i</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="pln">std</span><span class="pun">::</span><span class="pln">next</span><span class="pun">(</span><span class="pln">self</span><span class="pun">().</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> i</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span></pre>

<p>
	يوفّر الصنف أعلاه الدوالّ <code>‎front()‎</code> و <code>‎back()‎</code> و <code>‎size()‎</code> و <code>‎operator[]‎</code> لأي صنف فرعي يوفر الدالتين <code>‎begin()‎</code> و <code>‎end()‎</code>. في المثال التالي، يمكن للمصفوفات البسيطة المخصّصة ديناميكيًا أن تكون صنفًا فرعيًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_125" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;memory&gt;</span><span class="pln">
    </span><span class="com">// مصفوفة مخصّصة ديناميكيا</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">DynArray</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">Container</span><span class="pun">&lt;</span><span class="typ">DynArray</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> T</span><span class="pun">&gt;&gt;</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">public</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">using</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Container</span><span class="pun">&lt;</span><span class="typ">DynArray</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> T</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
        </span><span class="typ">DynArray</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> size</span><span class="pun">):</span><span class="pln"> size_
        </span><span class="pun">{</span><span class="pln">
            size
        </span><span class="pun">},</span><span class="pln">
        data_
        </span><span class="pun">{</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">make_unique </span><span class="pun">&lt;</span><span class="pln"> T</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">size_</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">}</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

        T</span><span class="pun">*</span><span class="pln"> begin</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> data_</span><span class="pun">.</span><span class="pln">get</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">const</span><span class="pln"> T</span><span class="pun">*</span><span class="pln"> begin</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> data_</span><span class="pun">.</span><span class="pln">get</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        T</span><span class="pun">*</span><span class="pln"> end</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> data_</span><span class="pun">.</span><span class="pln">get</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> size_</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">const</span><span class="pln"> T</span><span class="pun">*</span><span class="pln"> end</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> data_</span><span class="pun">.</span><span class="pln">get</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> size_</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">private</span><span class="pun">:</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> size_</span><span class="pun">;</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">unique_ptr </span><span class="pun">&lt;</span><span class="pln"> T</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> data_</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span></pre>

<p>
	يمكن الآن لمستخدمي الصنف <code>‎DynArray‎</code> استخدام الواجهات التي يوفّرها الصنف الأساسي CRTP بسهولة على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_127" style="">
<span class="typ">DynArray</span><span class="str">&lt;int&gt;</span><span class="pln"> arr</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln">
arr</span><span class="pun">.</span><span class="pln">front</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
arr</span><span class="pun">[</span><span class="lit">2</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">
assert</span><span class="pun">(</span><span class="pln">arr</span><span class="pun">.</span><span class="pln">size</span><span class="pun">()</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">10</span><span class="pun">);</span></pre>

<p>
	<strong>فائدة النمط</strong>: يتجنّب هذا النمط استدعاءات الدوالّ الوهمية في وقت التشغيل، والتي تسعى لاجتياز التسلسل الهرمي للوراثة، ويعتمد بدلًا من ذلك على التحويلات الساكنة (static casts):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_129" style="">
<span class="typ">DynArray</span><span class="str">&lt;int&gt;</span><span class="pln"> arr</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln">
</span><span class="typ">DynArray</span><span class="str">&lt;int&gt;</span><span class="pun">::</span><span class="typ">Base</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">base </span><span class="pun">=</span><span class="pln"> arr</span><span class="pun">;</span><span class="pln">
base</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">();</span><span class="pln">    </span><span class="com">// لا استدعاءات وهمية</span></pre>

<p>
	ويسمح التحويل الساكن الوحيد داخل الدالّة <code>‎begin()‎</code> في الصنف الأساسي <code>‎Container&lt;DynArray&lt;int&gt;&gt;‎</code> للمٌصرّف بتحسين الشيفرة بشكل كبير، إذ لن يحدث أي تنقيب في الجدول الوهمي (virtual table) في وقت التشغيل.
</p>

<p>
	<strong>عيوب النمط</strong>: نظرًا لأنّ الصنف الأساسي مُقوْلَب ويختلف من مصفوفة <code>‎DynArray‎</code> إلى أخرى، فلا يمكن تخزين المؤشّرات التي تشير إلى أصنافها الأساسية في مصفوفة متجانسة كما نفعل عمومًا مع الوراثة العادية التي لا يعتمد فيها الصنف الأساسي على الصنف المشتق:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_131" style="">
<span class="kwd">class</span><span class="pln"> A </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> B</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> A </span><span class="pun">{};</span><span class="pln">
A </span><span class="pun">*</span><span class="pln">a </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> B</span><span class="pun">;</span></pre>

<h3>
	استخدام أنماط CRTP لتجنّب تكرار الشيفرة
</h3>

<p>
	يوضّح المثال التالي كيفية استخدام CRTP لتجنّب تكرار الشيفرة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_133" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">IShape</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pun">~</span><span class="typ">IShape</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> accept</span><span class="pun">(</span><span class="typ">IShapeVisitor</span><span class="pln"> </span><span class="pun">&amp;)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Circle</span><span class="pun">:</span><span class="pln"> </span><span class="typ">IShape</span><span class="pln">
</span><span class="pun">{</span></pre>

<p>
	يجب على كل شكل أن يقدم هذا التابع بنفس الطريقة … ، نتابع المثال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_135" style="">
<span class="pln">    </span><span class="kwd">void</span><span class="pln"> accept</span><span class="pun">(</span><span class="typ">IShapeVisitor</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> visitor</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> override
    </span><span class="pun">{</span><span class="pln">
        visitor</span><span class="pun">.</span><span class="pln">visit</span><span class="pun">(*</span><span class="kwd">this</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// ...</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Square</span><span class="pun">:</span><span class="pln"> </span><span class="typ">IShape</span><span class="pln">
</span><span class="pun">{</span></pre>

<p>
	بالمثل هنا، يجب على كل شكل أن يقدم هذا التابع بنفس الطريقة، نتابع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_137" style="">
<span class="pln">    </span><span class="kwd">void</span><span class="pln"> accept</span><span class="pun">(</span><span class="typ">IShapeVisitor</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> visitor</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> override
    </span><span class="pun">{</span><span class="pln">
        visitor</span><span class="pun">.</span><span class="pln">visit</span><span class="pun">(*</span><span class="kwd">this</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// ...</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	يحتاج كل نوع فرعي من <code>‎IShape‎</code> إلى تنفيذ نفس الدالّة بنفس الطريقة، وهذا قد يأخذ الكثير من الوقت. الحل البديل هو تنفيذ نوع جديد في الهرمية الوراثية يتكفّل بفعل ذلك نيابة عنّا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_139" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Derived</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">IShapeAcceptor</span><span class="pun">:</span><span class="pln"> </span><span class="typ">IShape</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> accept</span><span class="pun">(</span><span class="typ">IShapeVisitor</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> visitor</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> override
        </span><span class="pun">{</span><span class="pln">
            visitor</span><span class="pun">.</span><span class="pln">visit</span><span class="pun">(*</span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Derived</span><span class="pln">
                </span><span class="kwd">const</span><span class="pun">*&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">this</span><span class="pun">));</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span></pre>

<p>
	والآن، يكفي أن ترث الأشكال من المتقبِّل (acceptor):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9405_141" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Circle</span><span class="pun">:</span><span class="pln"> </span><span class="typ">IShapeAcceptor</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Circle</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Circle</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Point</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">center</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> radius</span><span class="pun">):</span><span class="pln"> center</span><span class="pun">(</span><span class="pln">center</span><span class="pun">),</span><span class="pln"> radius</span><span class="pun">(</span><span class="pln">radius</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

    </span><span class="typ">Point</span><span class="pln"> center</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">double</span><span class="pln"> radius</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Square</span><span class="pun">:</span><span class="pln"> </span><span class="typ">IShapeAcceptor</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Square</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Square</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Point</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">topLeft</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> sideLength</span><span class="pun">):</span><span class="pln"> topLeft</span><span class="pun">(</span><span class="pln">topLeft</span><span class="pun">),</span><span class="pln"> sideLength</span><span class="pun">(</span><span class="pln">sideLength</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

    </span><span class="typ">Point</span><span class="pln"> topLeft</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">double</span><span class="pln"> sideLength</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	لم تعد هناك حاجة الآن إلى تكرار الشيفرة.
</p>

<p>
	هذا الدرس جزء من <a data-ss1617023042="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 78: Expression templates والفصل Chapter 79: Curiously Recurring Template Pattern (CRTP)‎ من كتاب <a data-ss1617023042="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">971</guid><pubDate>Wed, 02 Sep 2020 18:05:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x645;&#x639;&#x627;&#x644;&#x62C;&#x629; &#x627;&#x644;&#x623;&#x648;&#x644;&#x64A;&#x629; Preprocessor &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D9%85%D8%B9%D8%A7%D9%84%D8%AC%D8%A9-%D8%A7%D9%84%D8%A3%D9%88%D9%84%D9%8A%D8%A9-preprocessor-%D9%81%D9%8A-cpp-r970/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_08/41.png.d5f8cdaef2ac8087ef13cae4402c8994.png" /></p>

<p>
	معالج C الأولي هو محلّل/مبدّل نصوص يُشغَّل قبل التصريف الفعلي للشيفرة، ويُستخدم لتوسيع وتيسير استخدام لغة C (وكذلك C++‎ لاحقًا)، ويمكن استخدامه من أجل:
</p>

<ol>
<li>
		تضمين ملفّات أخرى باستخدام <code>‎#include‎</code>.
	</li>
	<li>
		تعريف شيفرة جامعة (macro)، لاستبدال النص باستخدام <code>‎#define‎</code>
	</li>
	<li>
		التصريف الشرطي باستخدام <code>‎#if‎</code> <code>‎#ifdef‎</code>.
	</li>
	<li>
		توجيه شيفرة معيّنة لمنصّة أو مٌصرّف معيّن (امتداد للتصريف الشرطي)
	</li>
</ol>
<h2>
	قيود التضمين
</h2>

<p>
	قد تُضمّن ترويسة من قبل ترويسة أخرى. لذلك، فالملفّات المصدرية التي تتضمّن عدّة ترويسات قد تتضمّن بعض الترويسات أكثر من مرّة بشكل غير مباشر. وإن كانت إحدى الترويسات المُضمّنة أكثر من مرّة تحتوي على تعريفات، فإنّّ المٌصرّف -بعد المعالجة الأوّلية- سيرصد انتهاكًا لقاعدة التعريف الواحد (الفقرة 3.2 من المعيار C++‎ لعام 2003) ومن ثم يحدث خطأ في التصريف.
</p>

<p>
	يمكن منع التضمين المتعدّد باستخدام دروع التضمين "include guards"، وتُعرَف أيضًا بدروع الترويسة، أو دروع الشيفرة الجامعة (macro guards). وتُنفَّذ هذه الدروع باستخدام مُوجِّهات المُعالج الأوّلي <code>‎#define‎</code> و <code>‎#ifndef‎</code> و <code>‎#endif‎</code>. انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_7" style="">
<span class="com">// Foo.h</span><span class="pln">
</span><span class="com">#ifndef</span><span class="pln"> FOO_H_INCLUDED
</span><span class="com">#define</span><span class="pln"> FOO_H_INCLUDED

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> </span><span class="com">// تعريف صنف</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="com">#endif</span></pre>

<p>
	الميزة الرئيسية لاستخدام دروع التضمين أنّها تعمل مع جميع المُصرّفات المتوافقة مع المعايير والمُعالجات الأوّلية.
</p>

<p>
	من ناحية أخرى، قد تخلق دروع التضمين بعض المشاكل للمطورين، لوجوب التأكد أنّ وحدات الشيفرة الجامعة فريدة في جميع الترويسات المُستخدمة في المشروع، خاصة إذا استَخدَمت ترويستين (أو أكثر) <code>‎FOO_H_INCLUDED‎</code> كدروع تضمين، فإنّّ أولى تلك الترويستين المُضمّنتين في وحدة تصريف ستمنع تضمين الترويسات الأخرى. هذه التحديات تظهر خاصّة إذا كان المشروع يستخدم مكتبات الطرف الثالث، والتي تحتوي على ترويسات تشترك في استخدام دروع تضمين.
</p>

<p>
	من الضروري أيضًا التأكد من أنّ وحدات الشيفرة الجامعة المستخدمة في دروع التضمين لا تتعارض مع وحدات الشيفرة الجامعة الأخرى المُعرَّفة في الترويسة.
</p>

<p>
	معظم تنفيذات C++‎ تدعم المُوجِّه <code>‎#pragma once‎</code> الذي يحرص على عدم تضمين الملفّ إلّا مرّة واحدة فقط في كل عمليّة تصريف، وهو مُوجِّه قياسي، لكنه ليس جزءًا من أيّ معيار من معايير ISO C++‎. مثلا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_9" style="">
<span class="com">// Foo.h</span><span class="pln">
</span><span class="com">#pragma</span><span class="pln"> once
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">{};</span></pre>

<p>
	في الشيفرة السابقة: بينما تُجنِّب <code>‎#pragma once‎</code> بعض المشاكل المرتبطة بدروع التضمين، فإنّ <code>‎#pragma‎</code> -حسب المعيار- هي بطبيعتها خُطَّاف خاص بالمٌصرّف (compiler-speciﬁc hook)، وستُتجاهل بصمت من قبل المٌصرّفات التي لا تدعمها. حمل المشاريع (أي porting) التي تستخدم <code>‎#pragma once‎</code> إلى المٌصرّفات التي لا تدعمها ليس بالأمر الهيّن.
</p>

<p>
	هناك عدد من إرشادات التشفير ومعايير C++‎ التي توصي بعدم استخدام أيّ مُعالج أوّلي إلا من أجل تضمين ملفات الترويسة <code>‎#include‎</code>، أو لأجل وضع دروع التضمين في الترويسات.
</p>

<h2>
	المنطق الشرطي والتعامل مع تعدد المنصات
</h2>

<p>
	باختصار، يتمحور منطق المعالجة الأوّلية الشرطية حول التحكم في جعل منطق الشيفرة متاحًا للتصريف أو غير متاح باستخدام تعاريف الشيفرات الجامعة.
</p>

<p>
	هذه ثلاث حالات استخدام أساسية:
</p>

<ul>
<li>
		عدّة إصدارات من تطبيق (مثلًا: إصدار للتنقيح، وآخر للإطلاق، وآخر للاختبار، وآخر للتحسين)
	</li>
	<li>
		التصريفات متعدّدة المنصات (cross-platform compiles) - نفس الشيفرة المصدرية، مع تصريفات لعدة منصات
	</li>
	<li>
		استخدام نفس الشيفرة لأجل عدة إصدارات من التطبيق (مثلًا: إصدار Basic و Premium و Pro من البرنامج) - مع ميزات مختلفة قليلاً.
	</li>
</ul>
<p>
	<strong>مثال أ</strong>: مقاربة متعددة المنصات لإزالة الملفّات:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_11" style="">
<span class="com">#ifdef</span><span class="pln"> _WIN32
</span><span class="com">#include</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">windows</span><span class="pun">.</span><span class="pln">h </span><span class="pun">&gt;</span><span class="pln">    </span><span class="com">// وبقية ملفات نظام ويندوز</span><span class="pln">

</span><span class="com">#endif</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;cstdio&gt;</span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> remove_file</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&amp;</span><span class="pln">path</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="com">#ifdef</span><span class="pln"> _WIN32
</span><span class="kwd">return</span><span class="pln"> </span><span class="typ">DeleteFile</span><span class="pun">(</span><span class="pln">path</span><span class="pun">.</span><span class="pln">c_str</span><span class="pun">());</span><span class="pln">
</span><span class="com">#elif</span><span class="pln"> defined</span><span class="pun">(</span><span class="pln">_POSIX_VERSION</span><span class="pun">)</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> defined</span><span class="pun">(</span><span class="pln">__unix__</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> remove</span><span class="pun">(</span><span class="pln">path</span><span class="pun">.</span><span class="pln">c_str</span><span class="pun">()));</span><span class="pln">
</span><span class="com">#elif</span><span class="pln"> defined</span><span class="pun">(</span><span class="pln">__APPLE__</span><span class="pun">)</span><span class="pln">

    </span><span class="com">//TODO: دالة مُخصّصة مع نافذة حوار للترخيص NSAPI التحقق مما إذا كان لـ</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> remove</span><span class="pun">(</span><span class="pln">path</span><span class="pun">.</span><span class="pln">c_str</span><span class="pun">()));</span><span class="pln">
</span><span class="com">#else</span><span class="pln">
</span><span class="com">#error</span><span class="pln"> </span><span class="str">"This platform is not supported"</span><span class="pln">
</span><span class="com">#endif</span><span class="pln">

</span><span class="pun">}</span></pre>

<p>
	<strong>مثال ب</strong>: إتاحة إمكانية التسجيل الإضافي لأجل التنقيح:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_13" style="">
<span class="kwd">void</span><span class="pln"> s_PrintAppStateOnUserPrompt</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"--------BEGIN-DUMP---------------\n"</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="typ">AppState</span><span class="pun">::</span><span class="typ">Instance</span><span class="pun">()-&gt;</span><span class="typ">Settings</span><span class="pun">().</span><span class="typ">ToString</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pln">
</span><span class="com">#if ( 1 == TESTING_MODE )  // الخصوصية: لا نريد  المعلومات الشخصية للمستخدم إلا عند الاختبار</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="typ">ListToString</span><span class="pun">(</span><span class="typ">AppState</span><span class="pun">::</span><span class="typ">UndoStack</span><span class="pun">()-&gt;</span><span class="typ">GetActionNames</span><span class="pun">())</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="typ">AppState</span><span class="pun">::</span><span class="typ">Instance</span><span class="pun">()-&gt;</span><span class="typ">CrntDocument</span><span class="pun">().</span><span class="typ">Name</span><span class="pun">()</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="typ">AppState</span><span class="pun">::</span><span class="typ">Instance</span><span class="pun">()-&gt;</span><span class="typ">CrntDocument</span><span class="pun">().</span><span class="typ">SignatureSHA</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pln">
</span><span class="com">#endif</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"--------END-DUMP---------------\n"</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>مثال ج</strong>: توفير ميزة مدفوعة (premium feature) في منتج منفصل (<strong>ملاحظة</strong>: هذا المثال توضيحي. من الأفضل إتاحة الميزة دون الحاجة إلى إعادة تثبيت التطبيق)
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_15" style="">
<span class="kwd">void</span><span class="pln"> </span><span class="typ">MainWindow</span><span class="pun">::</span><span class="typ">OnProcessButtonClick</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="com">#ifndef</span><span class="pln"> _PREMIUM
</span><span class="typ">CreatePurchaseDialog</span><span class="pun">(</span><span class="str">"Buy App Premium"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"This feature is available for our App Premium users. Click the Buy button to purchase the Premium version at our website"</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">return</span><span class="pun">;</span><span class="pln">
</span><span class="com">#endif</span><span class="pln">

            </span><span class="com">//… الميزات الفعلية هنا</span><span class="pln">
        </span><span class="pun">}</span></pre>

<p>
	بعض الطرق الشائعة:
</p>

<ul>
<li>
		تعريف رمز في وقت الاستدعاء (invocation): يمكن استدعاء المُعالج الأوّلي برموز مسبقة (مع تهيئة اختيارية). على سبيل المثال (<code>‎gcc -E‎</code> يعمل فقط على المُعالج الأوّلي):
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_17" style="">
<span class="pln">gcc </span><span class="pun">-</span><span class="pln"> E </span><span class="pun">-</span><span class="pln"> DOPTIMISE_FOR_OS_X </span><span class="pun">-</span><span class="pln"> DTESTING_MODE </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="typ">Sample</span><span class="pun">.</span><span class="pln">cpp</span></pre>

<p>
	يُعالَج Sample.cpp كما لو أنّ <code>‎#define OPTIMISE_FOR_OS_X‎</code> و <code>‎#define TESTING_MODE 1‎</code> مُضافان إلى أعلى Sample.cpp.
</p>

<ul>
<li>
		التأكد أن شيفرة جامعة ما معرَّفة: إذا لم تكن الشيفرة الجامعة مُعرّفة وقورنت قيمتها أو تم التحقق منها، فسيفترض المعالج الأوّلي دائمًا أنّ القيمة ستساوي <code>‎0‎</code>. وهناك عدّة طرق للتعامل مع هذا، إحداها هي افتراض أنّ الإعدادات الافتراضية تُمثَّل بالعدد 0، ويجب إجراء أيّ تغييرات لازمة بشكل صريح (على سبيل المثال ENABLE<em>EXTRA</em>DEBUGGING = 0 افتراضيًا، مع الإسناد -DENABLE<em>EXTRA</em>DEBUGGING = 1 لإعادة التعريف).
	</li>
</ul>
<p>
	هناك طريقة أخرى، وهي جعل جميع التعاريف والقيم الافتراضية صريحة، ويمكن تحقيق ذلك بدمج المُوجِّهين <code>‎#ifndef‎</code> و <code>‎#error‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_19" style="">
<span class="com">#ifndef</span><span class="pln"> </span><span class="pun">(</span><span class="pln">ENABLE_EXTRA_DEBUGGING</span><span class="pun">)</span><span class="pln">
</span><span class="com">// إن لم تكن مضافة سلفا DefaultDefines.h برجاء إضافة</span><span class="pln">
</span><span class="com"># error "ENABLE_EXTRA_DEBUGGING is not defined"</span><span class="pln">
</span><span class="com">#else</span><span class="pln">
</span><span class="com"># if ( 1 == ENABLE_EXTRA_DEBUGGING )</span><span class="pln">
</span><span class="com">//code</span><span class="pln">
</span><span class="com"># endif</span><span class="pln">
</span><span class="com">#endif</span></pre>

<h2>
	وحدات الشيفرة الجامعة التوليدية X-macros
</h2>

<p>
	هي تقنية اصطلاحية لتكرار توليد بنيات برمجية في وقت التصريف، وتتكون الشيفرات الجامعة التوليدية من جزأين: القائمة، وتنفيذ القائمة.
</p>

<p>
	هذا مثال توضيحي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_21" style="">
<span class="com">#define</span><span class="pln"> LIST\
X</span><span class="pun">(</span><span class="pln">dog</span><span class="pun">)</span><span class="pln">\
X</span><span class="pun">(</span><span class="pln">cat</span><span class="pun">)</span><span class="pln">\
X</span><span class="pun">(</span><span class="pln">racoon</span><span class="pun">)</span><span class="pln">
</span><span class="com">// class Animal {</span><span class="pln">
</span><span class="com">//    public:</span><span class="pln">
</span><span class="com">//      void say();</span><span class="pln">
</span><span class="com">// };</span><span class="pln">

</span><span class="com">#define</span><span class="pln"> X</span><span class="pun">(</span><span class="pln">name</span><span class="pun">)</span><span class="pln"> </span><span class="typ">Animal</span><span class="pln"> name</span><span class="pun">;</span><span class="pln">
LIST
</span><span class="com">#undef</span><span class="pln"> X

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{#</span><span class="pln">define X</span><span class="pun">(</span><span class="pln">name</span><span class="pun">)</span><span class="pln"> name</span><span class="pun">.</span><span class="pln">say</span><span class="pun">();</span><span class="pln">
    LIST
</span><span class="com">#undef</span><span class="pln"> X
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هذا المثال سيُوسَّع من قبل المعالج الأوّلي إلى ما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_23" style="">
<span class="typ">Animal</span><span class="pln"> dog</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Animal</span><span class="pln"> cat</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Animal</span><span class="pln"> racoon</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    dog</span><span class="pun">.</span><span class="pln">say</span><span class="pun">();</span><span class="pln">
    cat</span><span class="pun">.</span><span class="pln">say</span><span class="pun">();</span><span class="pln">
    racoon</span><span class="pun">.</span><span class="pln">say</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	عندما تصبح القوائم كبيرة (أكثر من 100 عنصر)، فإنّ هذه التقنية تساعد على تجنّب الإكثار من النسخ واللصق. وإذا أردت تجنّب التعريف غير الضروري لـ <code>‎X‎</code> قبل استخدام <code>‎LIST‎</code>، فيمكنك تمرير اسم شيفرة جامعة كوسيط أيضًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_25" style="">
<span class="com">#define</span><span class="pln"> LIST</span><span class="pun">(</span><span class="pln">MACRO</span><span class="pun">)</span><span class="pln">\
MACRO</span><span class="pun">(</span><span class="pln">dog</span><span class="pun">)</span><span class="pln">\
MACRO</span><span class="pun">(</span><span class="pln">cat</span><span class="pun">)</span><span class="pln">\
MACRO</span><span class="pun">(</span><span class="pln">racoon</span><span class="pun">)</span></pre>

<p>
	الآن، يمكنك تعريف الشيفرة الجامعة الذي يجب استخدامها عند توسيع القائمة، كما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_27" style="">
<span class="com">#define</span><span class="pln"> FORWARD_DECLARE_ANIMAL</span><span class="pun">(</span><span class="pln">name</span><span class="pun">)</span><span class="pln"> </span><span class="typ">Animal</span><span class="pln"> name</span><span class="pun">;</span><span class="pln">
LIST</span><span class="pun">(</span><span class="pln">FORWARD_DECLARE_ANIMAL</span><span class="pun">)</span></pre>

<p>
	إذا وجب على كل استدعاء لـ <code>‎MACRO‎</code> أن يأخذ معاملات إضافية ثابتة بالنسبة للقائمة، فيمكن استخدام وحدات شيفرات جامعة متغيّرة (variadic macros):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_29" style="">
<span class="com">// Visual studio</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> EXPAND</span><span class="pun">(</span><span class="pln">x</span><span class="pun">)</span><span class="pln"> x
</span><span class="com">#define</span><span class="pln"> LIST</span><span class="pun">(</span><span class="pln">MACRO</span><span class="pun">,</span><span class="pln"> </span><span class="pun">...)</span><span class="pln">\
EXPAND</span><span class="pun">(</span><span class="pln">MACRO</span><span class="pun">(</span><span class="pln">dog</span><span class="pun">,</span><span class="pln"> __VA_ARGS__</span><span class="pun">))</span><span class="pln">\
EXPAND</span><span class="pun">(</span><span class="pln">MACRO</span><span class="pun">(</span><span class="pln">cat</span><span class="pun">,</span><span class="pln"> __VA_ARGS__</span><span class="pun">))</span><span class="pln">\
EXPAND</span><span class="pun">(</span><span class="pln">MACRO</span><span class="pun">(</span><span class="pln">racoon</span><span class="pun">,</span><span class="pln"> __VA_ARGS__</span><span class="pun">))</span></pre>

<p>
	يُمرَّر الوسيط الأولى عبر <code>‎LIST‎</code>، بينما تُوفّر الوسائط الأخرى عبر المستخدم عند استدعاء <code>‎LIST‎</code>. مثلا، الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_31" style="">
<span class="com">#define</span><span class="pln"> FORWARD_DECLARE</span><span class="pun">(</span><span class="pln">name</span><span class="pun">,</span><span class="pln"> type</span><span class="pun">,</span><span class="pln"> prefix</span><span class="pun">)</span><span class="pln"> type prefix</span><span class="com">## name;</span><span class="pln">
LIST</span><span class="pun">(</span><span class="pln">FORWARD_DECLARE</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Animal</span><span class="pun">,</span><span class="pln"> anim_</span><span class="pun">)</span><span class="pln">
LIST</span><span class="pun">(</span><span class="pln">FORWARD_DECLARE</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Object</span><span class="pun">,</span><span class="pln"> obj_</span><span class="pun">)</span></pre>

<p>
	سوف تتوسع على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_33" style="">
<span class="typ">Animal</span><span class="pln"> anim_dog</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Animal</span><span class="pln"> anim_cat</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Animal</span><span class="pln"> anim_racoon</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Object</span><span class="pln"> obj_dog</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Object</span><span class="pln"> obj_cat</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Object</span><span class="pln"> obj_racoon</span><span class="pun">;</span></pre>

<h2>
	الشيفرات الجامعة Macros
</h2>

<p>
	تُصنّف وحدات الشيفرة الجامعة إلى مجموعتين رئيسيتين: وحدات الشيفرة الجامعة المشابهة للكائنات (object-like macros)، ووحدات الشيفرة الجامعة المشابهة للدوالّ (function-like macros). تُعامَل وحدات الشيفرة الجامعة كأداة لتعويض مقطع (token) معيّن من الشيفرة أثناء عملية التصريف، هذا يعني أنّه يمكن تجريد المقاطع الكبيرة (أو المكرّرة) من الشيفرة عبر شيفرة جامعة. انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_37" style="">
<span class="com">// هذه شيفرة جامعة تشبه الكائنات</span><span class="pln">
</span><span class="com">#define</span><span class="pln">    PI  </span><span class="lit">3.14159265358979</span></pre>

<p>
	هذه شيفرة جامعة تشبه الدوال، لاحظ أنه يُمكننا استخدام الشيفرَات الجامعة المُعرّفة مسبقًا في تعريفات شيفرة جامعة أخرى. ولا يعرف المصرِّف أيّ نوع يتعامل معه، لذلك يفضل استخدام الدوال المضمّنة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_39" style="">
<span class="com">#define</span><span class="pln">    AREA</span><span class="pun">(</span><span class="pln">r</span><span class="pun">)</span><span class="pln"> </span><span class="pun">(</span><span class="pln">PI </span><span class="pun">*(</span><span class="pln">r</span><span class="pun">)</span><span class="pln"> </span><span class="pun">*(</span><span class="pln">r</span><span class="pun">))</span><span class="pln">
</span><span class="com">// يمكن استخدامها على النحو التالي</span><span class="pln">
</span><span class="kwd">double</span><span class="pln"> pi_macro </span><span class="pun">=</span><span class="pln"> PI</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">double</span><span class="pln"> area_macro </span><span class="pun">=</span><span class="pln"> AREA</span><span class="pun">(</span><span class="lit">4.6</span><span class="pun">);</span></pre>

<p>
	تستخدم مكتبة Qt هذه التقنية لإنشاء نظام وصفي للكائنات (meta-object system) عن طريق مطالبة المستخدم بتعريف الشيفرة الجامعة Q_OBJECT في رأس الصنف الذي يوسّع QObject. وتُكتب أسماء وحدات الشيفرة الجامعة في العادة بأحرف كبيرة لتسهيل تمييزها عن الشيفرات العادية. هذا ليس شرطًا لكنّ يستحسنه كثير من المبرمجين.
</p>

<p>
	عند مصادفة شيفرة جامعة مشابهة للكائنات فإنها تُوسّع كعملية لصق-نسخ بسيطة، مع استبدال اسم الشيفرَة الجامعة بتعريفها. أمّا الشيفرات الجامعة المشابهة للدوال، فيُوسّع كلّ من اسمها ومعاملاتها.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_41" style="">
<span class="kwd">double</span><span class="pln"> pi_squared </span><span class="pun">=</span><span class="pln"> PI </span><span class="pun">*</span><span class="pln"> PI</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">double</span><span class="pln"> pi_squared </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3.14159265358979</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">3.14159265358979</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">double</span><span class="pln"> area </span><span class="pun">=</span><span class="pln"> AREA</span><span class="pun">(</span><span class="lit">5</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">double</span><span class="pln"> area </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">3.14159265358979</span><span class="pln"> </span><span class="pun">*(</span><span class="lit">5</span><span class="pun">)</span><span class="pln"> </span><span class="pun">*(</span><span class="lit">5</span><span class="pun">))</span></pre>

<p>
	وغالبًا ما تُوضع معاملات الشيفرة الجامعة الشبيهة بالدالّة (function-like macro parameters) بسبب هذا ضمن الأقواس، كما في <code>‎AREA()‎</code> أعلاه، وذلك لمنع أيّ أخطاء قد تحدث أثناء توسيع الشيفرة الجامعة، خاصة الأخطاء التي قد تنتج عن مُعاملات الشيفرة الجامعة التي تتألّف من عدة قيم.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_43" style="">
<span class="com">#define</span><span class="pln"> BAD_AREA</span><span class="pun">(</span><span class="pln">r</span><span class="pun">)</span><span class="pln"> PI </span><span class="pun">*</span><span class="pln">r </span><span class="pun">*</span><span class="pln">r
</span><span class="kwd">double</span><span class="pln"> bad_area </span><span class="pun">=</span><span class="pln"> BAD_AREA</span><span class="pun">(</span><span class="lit">5</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1.6</span><span class="pun">);</span><span class="pln">
</span><span class="com">// ما يراه المصرف:</span><span class="pln">
</span><span class="kwd">double</span><span class="pln"> bad_area </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3.14159265358979</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1.6</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1.6</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">double</span><span class="pln"> good_area </span><span class="pun">=</span><span class="pln"> AREA</span><span class="pun">(</span><span class="lit">5</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1.6</span><span class="pun">);</span><span class="pln">
</span><span class="com">// ما يراه المصرف:</span><span class="pln">
</span><span class="kwd">double</span><span class="pln"> good_area </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">3.14159265358979</span><span class="pln"> </span><span class="pun">*(</span><span class="lit">5</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1.6</span><span class="pun">)</span><span class="pln"> </span><span class="pun">*(</span><span class="lit">5</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1.6</span><span class="pun">));</span></pre>

<p>
	لاحظ أيضًا أنّه يجب توخي الحذر بخصوص المعاملات المُمرّرة إلى وحدات الشيفرة الجامعة بسبب هذا التوسيع البسيط، وذلك لمنع الآثار الجانبية غير المتوقعة. وإذا عُدِّل المُعامل أثناء التقييم فسيُعُدَّل في كل مرّة يُستخدَم في الشيفرة الجامعة الموسَّعة، ونحن لا نريد ذلك عادة. يبقى هذا صحيحًا حتى لو كانت الشيفرة الجامعة تُحيط المعاملات بالأقواس لمنع كسر الشيفرة بسبب التوسيع.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_45" style="">
<span class="typ">int</span><span class="pln"> oops </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">double</span><span class="pln"> incremental_damage </span><span class="pun">=</span><span class="pln"> AREA</span><span class="pun">(</span><span class="pln">oops</span><span class="pun">++);</span><span class="pln">
</span><span class="com">// ما يراه المصرف:</span><span class="pln">
</span><span class="kwd">double</span><span class="pln"> incremental_damage </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">3.14159265358979</span><span class="pun">*(</span><span class="pln">oops</span><span class="pun">++)*(</span><span class="pln">oops</span><span class="pun">++));</span></pre>

<p>
	بالإضافة إلى ذلك، لا توفّر وحدات الشيفرة الجامعة أيّ حماية من أخطاء الأنواع، ممّا يصعّب فهم الأخطاء الناتجة عن عدم تطابق الأنواع.
</p>

<p>
	ولمّا كان المبرمجون ينهون السطر بفاصلة منقوطة في العادة، فغالبًا ما تُصمَّم وحدات الشيفرة الجامعة المراد استخدامها كسطور مستقلة "لابتلاع" الفاصلة المنقوطة، هذا يمنع أيّ أخطاء غير مقصودة ناتجة عن وجود فاصلة منقوطة إضافية.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_47" style="">
<span class="com">#define</span><span class="pln"> IF_BREAKER</span><span class="pun">(</span><span class="typ">Func</span><span class="pun">)</span><span class="pln"> </span><span class="typ">Func</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">some_condition</span><span class="pun">)</span><span class="pln">
</span><span class="com">// Oops.</span><span class="pln">
IF_BREAKER</span><span class="pun">(</span><span class="pln">some_func</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">else</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"I am accidentally an orphan."</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></pre>

<p>
	في هذا المثال، كسرت الفاصلة المنقوطة المزدوجة غير المقصودة كتلة <code>‎if...else‎</code>، ومنعت المٌصرّف من مطابقة <code>‎else‎</code> بـ <code>‎if‎</code>. ولكي نمنع هذا، تُحذَف الفاصلة المنقوطة من تعريف الشيفرة الجامعة، ممّا يتسبب في "ابتلاع" الفاصلة المنقوطة مباشرةً بعد أيّ استخدام لها.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_49" style="">
<span class="com">#define</span><span class="pln"> IF_FIXER</span><span class="pun">(</span><span class="typ">Func</span><span class="pun">)</span><span class="pln"> </span><span class="typ">Func</span><span class="pun">()</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">some_condition</span><span class="pun">)</span><span class="pln">
    IF_FIXER</span><span class="pun">(</span><span class="pln">some_func</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">else</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Hooray!  I work again!"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></pre>

<p>
	يسمح ترك الفاصلة المنقوطة الزائدة أيضًا باستخدام الشيفرة الجامعة دون إنهاء التعليمة الحالية، وذلك يمكن أن يكون مفيدًا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_51" style="">
<span class="com">#define</span><span class="pln"> DO_SOMETHING</span><span class="pun">(</span><span class="typ">Func</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Param</span><span class="pun">)</span><span class="pln"> </span><span class="typ">Func</span><span class="pun">(</span><span class="typ">Param</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)</span><span class="pln">
</span><span class="com">// ...</span><span class="pln">

some_function</span><span class="pun">(</span><span class="pln">DO_SOMETHING</span><span class="pun">(</span><span class="pln">some_func</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">),</span><span class="pln"> DO_SOMETHING</span><span class="pun">(</span><span class="pln">some_func</span><span class="pun">,</span><span class="pln"> </span><span class="lit">42</span><span class="pun">));</span></pre>

<p>
	عادة، ينتهي تعريف الشيفرة الجامعة في نهاية السطر، فإذا احتاجت الشيفرة الجامعة إلى أن تمتدّ على عدّة أسطر، فيمكن استخدام شرطة عكسية <code>\</code> في نهاية السطر للإشارة إلى ذلك. ويجب أن تكون هذه المشروطة العكسية هي الحرف الأخير من السطر، فذلك يُخطر المُعالج الأوّلي بوجوب ضمّ السطر التالي إلى السطر الحالي، ومعاملتهُما كسطرٍ واحد. يمكن استخدام هذا عدّة مرات على التوالي.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_53" style="">
<span class="com">#define</span><span class="pln"> TEXT </span><span class="str">"</span><span class="pln">I \
am \
many \
lines</span><span class="pun">.</span><span class="str">"</span><span class="pln">
</span><span class="com">// ...</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> TEXT </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">    </span><span class="com">//   I am many lines.</span></pre>

<p>
	هذا مفيد بشكل خاص في وحدات الشيفرة الجامعة المعقّدة الشبيهة بالدوالّ، والتي قد تحتاج إلى الامتداد على عدّة أسطر.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_55" style="">
<span class="com">#define</span><span class="pln"> CREATE_OUTPUT_AND_DELETE</span><span class="pun">(</span><span class="typ">Str</span><span class="pun">)</span><span class="pln"> \
std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">*</span><span class="pln"> tmp </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">(</span><span class="typ">Str</span><span class="pun">);</span><span class="pln"> \
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln">tmp </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln"> \
</span><span class="kwd">delete</span><span class="pln"> tmp</span><span class="pun">;</span><span class="pln">
</span><span class="com">// ...</span><span class="pln">
CREATE_OUTPUT_AND_DELETE</span><span class="pun">(</span><span class="str">"There's no real need for this to use 'new'."</span><span class="pun">)</span></pre>

<p>
	أمّا بخصوص وحدات الشيفرة الجامعة المعقدة الشبيهة بالدوالّ، فقد يكون من المفيد منحها نطاقًا خاصًّا بها لمنع التداخلات في الأسماء أو التسبب في تدمير الكائنات في نهاية الشيفرة الجامعة، وذلك على غرار الدوالّ الفعلية.
</p>

<p>
	المقاربة الشائعة لهذا هي استخدام الحلقة <code>do while 0</code>، حيث تُوضع الشيفرة الجامعة في كتلة التكرار. لا تُتبع هذه الكتلة عادة بفاصلة منقوطة، ممّا يسمح لها بابتلاع واحدة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_57" style="">
<span class="com">#define</span><span class="pln"> DO_STUFF</span><span class="pun">(</span><span class="typ">Type</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Param</span><span class="pun">,</span><span class="pln"> </span><span class="typ">ReturnVar</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">do</span><span class="pln"> </span><span class="pun">{</span><span class="pln">\
    </span><span class="typ">Type</span><span class="pln"> temp</span><span class="pun">(</span><span class="pln">some_setup_values</span><span class="pun">);</span><span class="pln">\
    </span><span class="typ">ReturnVar</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> temp</span><span class="pun">.</span><span class="pln">process</span><span class="pun">(</span><span class="typ">Param</span><span class="pun">);</span><span class="pln">\
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0</span><span class="pun">)</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
DO_STUFF</span><span class="pun">(</span><span class="typ">MyClass</span><span class="pun">,</span><span class="pln"> </span><span class="lit">41153.7</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">);</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">do</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">MyClass</span><span class="pln"> temp</span><span class="pun">(</span><span class="pln">some_setup_values</span><span class="pun">);</span><span class="pln">
    x </span><span class="pun">=</span><span class="pln"> temp</span><span class="pun">.</span><span class="pln">process</span><span class="pun">(</span><span class="lit">41153.7</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0</span><span class="pun">);</span></pre>

<p>
	هناك أيضًا وحدات شيفرة جامعة متغايرة (variadic)، والتي تأخذ عددًا متغيّرا من الوسائط، ثم توسّعها جميعًا بدلاً من المُعامل الخاص <code>‎__VA_ARGS__‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_59" style="">
<span class="com">#define</span><span class="pln"> VARIADIC</span><span class="pun">(</span><span class="typ">Param</span><span class="pun">,</span><span class="pln"> </span><span class="pun">...)</span><span class="pln"> </span><span class="typ">Param</span><span class="pun">(</span><span class="pln">__VA_ARGS__</span><span class="pun">)</span><span class="pln">
VARIADIC</span><span class="pun">(</span><span class="pln">printf</span><span class="pun">,</span><span class="pln"> </span><span class="str">"%d"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">);</span><span class="pln">
</span><span class="com">// ما يراه المصرِّف:</span><span class="pln">
printf</span><span class="pun">(</span><span class="str">"%d"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">);</span></pre>

<p>
	لاحظ أنّه يمكن وضع <code>‎__VA_ARGS__‎</code> أثناء التوسيع في أيّ مكان في التعريف، وسيُوسّع بشكل صحيح.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_61" style="">
<span class="com">#define</span><span class="pln"> VARIADIC2</span><span class="pun">(</span><span class="typ">POne</span><span class="pun">,</span><span class="pln"> </span><span class="typ">PTwo</span><span class="pun">,</span><span class="pln"> </span><span class="typ">PThree</span><span class="pun">,</span><span class="pln"> </span><span class="pun">...)</span><span class="pln"> </span><span class="typ">POne</span><span class="pun">(</span><span class="typ">PThree</span><span class="pun">,</span><span class="pln"> __VA_ARGS__</span><span class="pun">,</span><span class="pln"> </span><span class="typ">PTwo</span><span class="pun">)</span><span class="pln">
VARIADIC2</span><span class="pun">(</span><span class="pln">some_func</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pun">);</span><span class="pln">
some_func</span><span class="pun">(</span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">);</span></pre>

<p>
	في حالة المعامِل المتغير الذي ليس له وسائط، فإنّ المٌصرّفات تتعامل مع الفاصلة الزائدة بشكل مختلف، حيث تبتلع بعض المُصرّفات -مثل Visual Studio- الفاصلة بصمت بدون أيّ صيغة خاصّة، فيما ستطلّب منك مُصرّفات أخرى -مثل GCC- وضع <code>‎##‎</code> مباشرة قبل <code>‎__VA_ARGS__‎</code>. ويكون من الحكمة بسبب هذا أن تضع تعريف وحدات الشيفرة الجامعة التي تأخذ عددًا متغيّرا من الوسائط في عبارة شرطية إذا كنت حريصًا على قابلية الشيفرة للعمل في أكثر من مكان. في المثال التالي: <code>COMPILER</code> هو شيفرة جامعة تحدد المصرِّف المستخدم.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_63" style="">
<span class="com">#if COMPILER == "VS"</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> VARIADIC3</span><span class="pun">(</span><span class="typ">Name</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Param</span><span class="pun">,</span><span class="pln"> </span><span class="pun">...)</span><span class="pln"> </span><span class="typ">Name</span><span class="pun">(</span><span class="typ">Param</span><span class="pun">,</span><span class="pln"> __VA_ARGS__</span><span class="pun">)</span><span class="pln">
</span><span class="com">#elif</span><span class="pln"> COMPILER </span><span class="pun">==</span><span class="pln"> </span><span class="str">"GCC"</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> VARIADIC3</span><span class="pun">(</span><span class="typ">Name</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Param</span><span class="pun">,</span><span class="pln"> </span><span class="pun">...)</span><span class="pln"> </span><span class="typ">Name</span><span class="pun">(</span><span class="typ">Param</span><span class="pun">,</span><span class="pln"> </span><span class="com">##__VA_ARGS__)</span><span class="pln">
</span><span class="com">#endif</span><span class="pln"> </span><span class="com">/* COMPILER */</span></pre>

<h2>
	الشيفرات الجامعة المُعرّفة مسبقًا (Predeﬁned macros)
</h2>

<p>
	الشيفرة الجامعة المُعرّفة مسبقًا هي تلك التي يعرّفها المٌصرّف -على النقيض من تلك التي يعرّفها المستخدمون في الملف المصدري-، ويجب ألّا يُعاد تعريف تلك الشيفرات الجامعة أو إلغاء تعريفها من قِبل المستخدم.
</p>

<p>
	الشيفرات الجامعة التالية مُعرّفة مسبقًا وفقًا لمعيار C++‎:
</p>

<ul>
<li>
		<code>‎__LINE__‎</code> - تحتوي على رقم السطر الذي تُسُتخدم فيه هذه الشيفرة الجامعة، ويمكن تغييرها عبر المُوجِّه <code>‎‎</code>#line.
	</li>
	<li>
		<code>‎__FILE__‎</code> - تحتوي على اسم الملفّ الذي تُستخدم فيه هذه الشيفرة الجامعة في، ويمكن تغييرها عبر المُوجِّه <code>‎‎#line</code>.
	</li>
	<li>
		<code>‎__DATE__‎</code> - تحتوي تاريخ تصريف الملف (بتنسيق "Mmm dd yyyy")، ويتم تنسيق Mmm كما لو كانت مُعادة من قبل <code>‎std::asctime()‎</code>.
	</li>
	<li>
		<code>‎__TIME__‎</code> - تحتوي زمن تصريف الملف وفق التنسيق "HH: MM: SS".
	</li>
	<li>
		<code>‎__cplusplus‎</code> - تُعرَّف من قبل مصرّف C++‎ أثناء تصريف ملفات C++‎، وقيمتها هي الإصدار القياسي الذي يتوافق مع المٌصرّف، أي <code>‎199711L‎</code> لـ C++‎ 98 و C++‎ 03، و <code>‎201103L‎</code> لـ C++‎ 11، و <code>‎201402L‎</code> لمعيار C++‎ 14.
	</li>
</ul>
<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<ul>
<li>
		<code>‎__STDC_HOSTED__‎</code> - تُعطى القيمة <code>‎1‎</code> إذا كان التطبيق مُستضافًا (hosted)، أو <code>‎0‎</code> إذا كان قائما بذاته (freestanding).
	</li>
</ul>
<p>
	<strong>الإصدار ≥ C++‎ 17</strong>
</p>

<ul>
<li>
		<code>‎__STDCPP_DEFAULT_NEW_ALIGNMENT__‎</code> - تحتوي على <code>size_t</code> حرفية، والتي تمثّل المحاذاة المستخدمة لإجراء استدعاء للعامل <code>‎operator new‎</code> غير المدرِك للمحاذاة.
	</li>
</ul>
<p>
	بالإضافة إلى ذلك، يُسمح للشيفرة الجامعة التالية أن تُعرَّف مسبقًا من قبل التنفيذات، لكنّها غير إلزامية:
</p>

<ul>
<li>
		<code>‎__STDC__‎</code> - يعتمد معناها على التنفيذ، ولا تٌعرَّف عادة إلّا عند تصريف ملف في لغة C للدلالة على الامتثال الكامل مع معيار C القياسي، أو قد لا تُنفّد إذا قرّر المٌصرّف عدم دعم هذه الشيفرة الجامعة.
	</li>
</ul>
<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<ul>
<li>
		<code>‎__STDC_VERSION__‎</code> - يعتمد معناها على التنفيذ، وعادة ما تساوي قيمتها إصدارَ لغة C، على نحو مشابه لـ <code>‎__cplusplus‎</code> في إصدار C++‎، أو قد لا تُعرَّف، إذا قرر المٌصرّف عدم دعم هذه الشيفرة الجامعة.
	</li>
	<li>
		<code>‎__STDC_MB_MIGHT_NEQ_WC__‎</code> - تُعطى القيمة <code>‎1‎</code>، إذا كان ممكنًا لقيم الترميز الضيق لمجموعة المحارف الأساسية، ألا تساوي قيم نظرائها الواسعة، مثلًا في حال كان <code>‎(uintmax_t)'x' != (uintmax_t)L'x'‎</code>.
	</li>
	<li>
		<code>‎__STDC_ISO_10646__‎</code> - تُعرّف في حال كان <code>wchar_t</code> مُرمّزًا بترميز اليونيكود (Unicode)، وتُوسّع إلى عدد صحيح على شكل <code>‎yyyymmL‎</code> إشارةً إلى دعم آخر مُراجَعة لليونيكود.
	</li>
	<li>
		<code>‎__STDCPP_STRICT_POINTER_SAFETY__‎</code> - تُعطى القيمة <code>‎1‎</code> إذا كان للتنفيذ نظام أمان صارم للمؤشّرات (strict pointer safety)
	</li>
	<li>
		<code>‎__STDCPP_THREADS__‎</code> - تُعطى القيمة <code>‎1‎</code> إذا أمكن احتواء البرنامج على أكثر من خيط (thread) واحد للتنفيذ، ينطبق هذا على التنفيذ المستقل (freestanding implementation) أما التنفيذات المستضافة فيمكن أن يكون لها أكثر من خيط واحد.
	</li>
</ul>
<p>
	ربما تجب الإشارة إلى <code>‎__func__‎</code>، وهي ليست شيفرة جامعة ولكنّها متغيِّر محلّي لدالّة مُعرّفة مُسبقا (predeﬁned function-local variable). يحتوي هذا المتغير على اسم الدالّة التي تُستخدَم فيها على شكل مصفوفة حروف ساكنة وفق تنسيق مُعرّف من قِبل التنفيذ.
</p>

<p>
	ويمكن أن يكون للمٌصرّفات مجموعة خاصّة بها من وحدات الشيفرة الجامعة المسبقة، وذلك إضافة إلى وحدات الشيفرة الجامعة القياسية المُعرّفة مسبقًا، ارجع إن شئت إلى توثيق المٌصرّف للاطلاع عليها. على سبيل المثال:
</p>

<ul>
<li>
		<a data-ss1617023043="1" href="https://gcc.gnu.org/onlinedocs/cpp/Predefined-Macros.html" rel="external nofollow">gcc</a>
	</li>
	<li>
		<a data-ss1617023043="1" href="https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?redirectedfrom=MSDN&amp;view=vs-2019#Anchor_2" rel="external nofollow">Microsoft Visual C++‎‎</a>
	</li>
	<li>
		<a data-ss1617023043="1" href="http://clang.llvm.org/docs/LanguageExtensions.html#builtin-macros" rel="external nofollow">clang</a>
	</li>
	<li>
		<a data-ss1617023043="1" href="https://software.intel.com/en-us/node/514528" rel="external nofollow">Intel C++ Compiler</a>
	</li>
</ul>
<p>
	توجد بعض تلك الشيفرات الجامعة للاستعلام عن دعم بعض الميزات فقط:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_65" style="">
<span class="com">#ifdef</span><span class="pln"> __cplusplus   </span><span class="com">// C++ في حال صُرِّفت عبر مصرّف</span><span class="pln">
</span><span class="kwd">extern</span><span class="pln"> </span><span class="str">"C"</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">//C يجب أن تُزخرَف شيفرة </span><span class="pln">
    </span><span class="com">// هنا C ترويسة مكتبة</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">#endif</span></pre>

<p>
	البعض الآخر مفيدة جدًا للتنقيح:
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_67" style="">
<span class="kwd">bool</span><span class="pln"> success </span><span class="pun">=</span><span class="pln"> doSomething</span><span class="pun">(</span><span class="pln"> </span><span class="com">/*some arguments*/</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="kwd">if</span><span class="pun">(</span><span class="pln"> </span><span class="pun">!</span><span class="pln">success </span><span class="pun">){</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cerr </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"ERROR: doSomething() failed on line "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> __LINE__ </span><span class="pun">-</span><span class="pln"> </span><span class="lit">2</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" in function "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> __func__ </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"()"</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" in file "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> __FILE__
</span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	والبعض الآخر للتحكم في الإصدار:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_69" style="">
<span class="typ">int</span><span class="pln"> main</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> argc</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">*</span><span class="pln">argv</span><span class="pun">[])</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pun">(</span><span class="pln"> argc </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">(</span><span class="pln"> argv</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="str">"-v"</span><span class="pln"> </span><span class="pun">){</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Hello World program\n"</span><span class="pln">
            </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"v 1.1\n"</span><span class="pln">   </span><span class="com">// عليك تحديث هذا يدويا</span><span class="pln">
            </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"compiled: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> __DATE__ </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">' '</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> __TIME__    </span><span class="com">// هذا يُحدّث تلقائيا</span><span class="pln">
            </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">else</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Hello World!\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	عمليات المعالجة الأولية
</h2>

<p>
	يُستخدم المُعامل <code>‎#‎</code> أو مُعامل التنصيص (stringizing operator) لتحويل مُعامل شيفرة جامعة إلى سلسلة نصية، ولا يمكن استخدامه إلّا مع شيفرة جامعة ذات وسائط. انظر المثال التالي حيث يحول المعالج الأولي المعامِلَ <code>x</code> إلى السلسلة النصية المجردة <code>x</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_71" style="">
<span class="com">#define</span><span class="pln"> PRINT</span><span class="pun">(</span><span class="pln">x</span><span class="pun">)</span><span class="pln"> printf</span><span class="pun">(#</span><span class="pln">x </span><span class="str">"\n"</span><span class="pun">)</span><span class="pln">
PRINT</span><span class="pun">(</span><span class="typ">This</span><span class="pln"> line will be converted to string by preprocessor</span><span class="pun">);</span><span class="pln">
printf</span><span class="pun">(</span><span class="str">"This line will be converted to string by preprocessor"</span><span class="pln">
    </span><span class="str">"\n"</span><span class="pun">);</span></pre>

<p>
	يضمّ المُصرّف سلسلتين نصّيتين إلى بعضهما، وسيكون الوسيط <code>‎printf()‎</code> النهائي عبارة عن سلسلة نصية مجردة تنتهي بمحرف السطر الجديد. وسيتجاهل المُعالج الأوّلي المسافات البيضاء الموجودة قبل أو بعد وسيط الشيفرة الجامعة، لذلك ستطبع الشيفرة التالية نفس النتيجة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_75" style="">
<span class="pln">PRINT</span><span class="pun">(</span><span class="typ">This</span><span class="pln"> line will be converted to string by preprocessor</span><span class="pun">);</span></pre>

<p>
	إذا تطلب مُعامل السلسلة النصية المجردة تسلسل تهريب (escape sequence)، كما هو الحال قبل علامة الاقتباس المزدوجة، فسيُدرَج تلقائيًا عبر المعالج الأوّلي.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_77" style="">
<span class="pln">PRINT</span><span class="pun">(</span><span class="typ">This</span><span class="pln"> </span><span class="str">"line"</span><span class="pln"> will be converted to </span><span class="str">"string"</span><span class="pln"> by preprocessor</span><span class="pun">);</span><span class="pln">
printf</span><span class="pun">(</span><span class="str">"This \"line\" will be converted to \"string\" by preprocessor""\n"</span><span class="pun">);</span></pre>

<p>
	يُستخدم العامل <code>‎##‎</code> أو عامل لصق القِطع (Token pasting operator) لضمّ سلسلتين نصّيتين أو مقطعَين خاصين بشيفرة جامعة. انظر المثال التالي حيث يدمج المعالجُ الأولي المتغيرَ مع <code>x</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_79" style="">
<span class="com">#define</span><span class="pln"> PRINT</span><span class="pun">(</span><span class="pln">x</span><span class="pun">)</span><span class="pln"> printf</span><span class="pun">(</span><span class="str">"variable"</span><span class="pln"> </span><span class="com">#x " = %d", variable##x)</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> variableY </span><span class="pun">=</span><span class="pln"> </span><span class="lit">15</span><span class="pun">;</span><span class="pln">
PRINT</span><span class="pun">(</span><span class="pln">Y</span><span class="pun">);</span><span class="pln">

printf</span><span class="pun">(</span><span class="str">"variable""Y"" = %d"</span><span class="pun">,</span><span class="pln"> variableY</span><span class="pun">);</span></pre>

<p>
	وسنحصل على الناتج التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_81" style="">
<span class="pln">variableY </span><span class="pun">=</span><span class="pln"> </span><span class="lit">15</span></pre>

<h2>
	‎‎ #pragma once
</h2>

<p>
	تدعم معظم تطبيقات C++‎ المُوجِّه <code>‎#pragma once‎</code> الذي يتحقّق من أنّ الملفّ لن يُضمَّن إلّا مرّة واحدة في كل عملية تصريف، وهو ليس جزءًا من أيّ معيار من معايير ISO C++‎.
</p>

<p>
	على سبيل المثال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_83" style="">
<span class="com">// Foo.h</span><span class="pln">
</span><span class="com">#pragma</span><span class="pln"> once
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">{};</span></pre>

<p>
	بينما تتجنب <code>‎#pragma once‎</code> بعض المشاكل المرتبطة بدروع التضمين (include guards) التي ذكرناها آنفًا، فإنّ <code>‎#pragma‎</code> -حسب تعريفها في المعايير- هي خطّاف خاصّ بالمٌصرّف (compiler-speciﬁc hook)، وسيُتجاهَل بصمت من قبل المٌصرّفات التي لا تدعمه.
</p>

<p>
	ويجب تعديل المشاريع التي تستخدم <code>‎#pragma once‎</code> لتكون متوافقة مع المعايير، وقد يؤدّي <code>‎#pragma once‎</code> إلى تسريع كبير لعملية التصريف في بعض المُصرِّفات -خاصّة تلك التي تستخدم الترويسات المُصرّفة مسبقًا-. وبالمثل، تسرّع بعض المُعالجات الأوّلية عملية التصريف من خلال التحقق من الترويسات المُتضمّنة التي تستخدم الدروع.
</p>

<p>
	قد تزيد الفائدة من استخدام كل من <code>‎#pragma once‎</code> والدروع معًا أو تنقص بحسب التنفيذ ووقت التصريف. وقد كان يوصى بدمج <code>‎#pragma once‎</code> مع دُروع التضمين عند كتابة تطبيقات MFC على ويندوز، وكانت تُنشأ بواسطة الأدوات <code>‎add class‎</code> و <code>‎add dialog‎</code> و <code>‎add windows‎</code> الخاصة بـ Visual Studio، لذا من الشائع أن تجدها في تطبيقات C++‎ الموجّهة لويندوز.
</p>

<h2>
	رسائل خطأ المُعالج الأوّلي
</h2>

<p>
	يمكن توليد أخطاء التصريف باستخدام المعالج الأوّلي، هذا مفيد لعدد من الأسباب:
</p>

<ul>
<li>
		إخطار المستخدم في حال كان على منصّة أو مٌصرّف غير مدعوم.
	</li>
	<li>
		إعادة خطأ في حال كان الإصدار أقل من gcc 3.0.0.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_85" style="">
<span class="com">#if __GNUC__ &lt; 3</span><span class="pln">
</span><span class="com">#error</span><span class="pln"> </span><span class="str">"This code requires gcc &gt; 3.0.0"</span><span class="pln">
</span><span class="com">#endif</span></pre>

<p>
	إعادة خطأ إن كان التصريف على حاسوب Apple.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9554_87" style="">
<span class="com">#ifdef</span><span class="pln"> __APPLE__
</span><span class="com">#error</span><span class="pln"> </span><span class="str">"Apple products are not supported in this release"</span><span class="pln">
</span><span class="com">#endif</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617023043="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة مقالات عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 75: Preprocessor من كتاب <a data-ss1617023043="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">970</guid><pubDate>Mon, 31 Aug 2020 18:02:00 +0000</pubDate></item><item><title>&#x641;&#x626;&#x627;&#x62A; &#x627;&#x644;&#x642;&#x64A;&#x645; Value Categories &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D9%81%D8%A6%D8%A7%D8%AA-%D8%A7%D9%84%D9%82%D9%8A%D9%85-value-categories-%D9%81%D9%8A-cpp-r969/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_10/40.png.3148722a5b65876148fb5cba14fb711b.png.7726d349fb406ab2c9ef1b180419f565.png" /></p>

<p>
	تُسنَد فئات القيمة إلى تعبيرات C++‎ بناءً على نتائج تلك التعبيرات، ويمكن لهذه الفئات أن تؤثّر على <a data-ss1617023044="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-22-%D8%A7%D9%84%D8%AA%D8%AD%D9%85%D9%8A%D9%84-%D8%A7%D9%84%D8%B2%D8%A7%D8%A6%D8%AF-overloading-%D8%AA%D8%AD%D9%84%D9%8A%D9%84%D9%87-%D9%88%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D9%87-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D9%81%D9%8A-cpp-r934/" rel="">تحليل التحميل الزائد</a> (overload resolution) للدوالّ في C++‎، كما تحدّد خاصّيتين مهمَّتين ومنفصلتين حول التعابير، تحدد الأول منهما إذا كان للتعبير هوية (identity)، أي إذا كان يشير إلى كائن له اسمُ متغيّرٍ (variable name)، حتى لو لم يكن اسم المتغيّر مُضمَّنًا في التعبير. والثانية هي إذا كان يجوز النقل ضمنيًا (implicitly move) من قيمة التعبير، أو بشكل أدقّ، إذا كان التعبير سيرتبط بأنواع المعاملات ذات القيمة اليمينية (r-value parameter types) عند استخدامه كمُعامل دالة أم لا.
</p>

<p>
	تُعرّف C++‎ ثلاث فئات تمثّل مجموعة من هذه الخصائص:
</p>

<ul>
<li>
		lvalue - تعبير يساري (تعبيرات ذات هوّية، ولكن لا يمكن النقل منها).
	</li>
	<li>
		xvalue - تعبير مرتحل (تعبيرات ذات هوّية ويمكن النقل منها).
	</li>
	<li>
		prvalue - تعبير يميني خالص (تعبيرات بدون هوية ويمكن النقل منها).
	</li>
</ul>
<p>
	لا تحتوي C++‎ على تعبيرات ليس لها هوية ولا يمكن النقل منها. من ناحية أخرى، تعرّف C++‎ فئتي قيمَة أخريين، كل منهما تعتمد حصرًا على إحدى هذه الخصائص:
</p>

<ul>
<li>
		glvalue - تعبير يساري مُعمّم النوع (تعبيرات ذات هوية)
	</li>
	<li>
		rvalue - تعبير يميني (تعبيرات يمكن النقل منها).
	</li>
</ul>
<p>
	ويمكن استخدام هذه كمجموعات لتصنيف الفئات السابقة. انظر هذا الرسم للتوضيح:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="50219" data-ss1617023044="1" href="https://academy.hsoub.com/uploads/monthly_2020_08/C09fH.png.93e4bb482b612f01a8630c1fdc832611.png" rel=""><img alt="C09fH.png" class="ipsImage ipsImage_thumbnailed" data-fileid="50219" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_08/C09fH.png.93e4bb482b612f01a8630c1fdc832611.png"></a>
</p>

<h2>
	القيم اليمينيّة rvalue
</h2>

<p>
	التعبير اليمينيّ rvalue هو أيّ تعبير يمكن نقله ضمنيًا بغض النظر عما إذا كانت له هوية. وبتعبير أدق، يمكن استخدام التعبيرات اليمينيّة كوسائط للدوال التي تأخذ مُعاملات من النوع <code>‎T &amp;&amp;‎</code> ( يمثّل <code>‎T‎</code> نوع التعبير <code>‎expr‎</code>)، والتعبيرات اليمينية هي وحدها التي يمكن تمريرها كوسائط لمعاملات مثل هذه الدوالّ. أما في حال استخدام تعبير غير يميني فإنّّ تحليل التحميل الزائد سيختار أيّ دالّة لا تستخدم مرجع يمينيًا (rvalue reference)، وسيطلق خطأً في حال تعذّر العثور عليها.
</p>

<p>
	تشمل فئة التعبيرات اليمينية حصرًا جميع تعبيرات <code>xvalue</code> و <code>prvalue</code>، وتحوّل دالّة المكتبة القياسية <code>‎std::move‎</code> تعبيرًا غير يمينيّ بشكل صريح إلى تعبير يميني، إذ تحوّل التعبير إلى تعبير من الفئة <code>xvalue</code>، فحتى لو كان التعبير يمينيا خالصًا ناقص الهوية (identity-less prvalue) من قبل، فإنّه سيكتسب هويةً -اسم معامِل الدالة- عبر تمريره كمُعامل إلى <code>‎std::move‎</code>، ويصبح من الفئة xvalue. انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7589_7" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">string str</span><span class="pun">(</span><span class="str">"init"</span><span class="pun">);</span><span class="pln"> </span><span class="com">//1</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string test1</span><span class="pun">(</span><span class="pln">str</span><span class="pun">);</span><span class="pln"> </span><span class="com">//2</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string test2</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">str</span><span class="pun">));</span><span class="pln"> </span><span class="com">//3</span><span class="pln">

str </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">(</span><span class="str">"new value"</span><span class="pun">);</span><span class="pln"> </span><span class="com">//4</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&amp;&amp;</span><span class="pln">str_ref </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">str</span><span class="pun">);</span><span class="pln"> </span><span class="com">//5</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string test3</span><span class="pun">(</span><span class="pln">str_ref</span><span class="pun">);</span><span class="pln"> </span><span class="com">//6</span></pre>

<p>
	يأخذ منشئ السلاسل النصية مُعاملًا واحدًا من النوع <code>std::string‎&amp;&amp;‎‏‏‎</code>، ويُطلق على هذا المنشئ عادة "منشئ النقل" (move constructor)، لكن فئة القيمة الخاصة بـ <code>‎str‎</code> ليست يمينيّة (بل يساريّة)، لذا لا يمكن استدعاء التحميل الزائد للمنشئ. وبدلاً من ذلك يُستدعي التحميل الزائد لـ <code>‎const std::string&amp;‎</code>، أي مُنشئ النسخ.
</p>

<p>
	تتغير الأمور في السطر الثالث حيث تكون القيمة المُعادة من <code>‎std::move‎</code> هي <code>‎T&amp;&amp;‎</code>، إذ يمثّل <code>‎T‎</code> النوع الأساسي للمُعامِل المُمرّر، لذا فإنّّ <code>‎std::move(str)‎</code> تُعيد <code>‎std::string&amp;&amp;‎</code>. واستدعاء الدالة الذي تكون قيمته المعادة مرجعًا يمينيًا (rvalue reference) يُعدُّ تعبيرًا يمينيًا، وتحديدًا من فئة <code>xvalue</code>، لذا قد تستدعي منشئَ النقلِ للسلسلة النصية <code>std::string</code>. بعد ذلك، أي بعد السطر الثالث، يكون النقل من <code>str</code> قد تم، وصارت محتويات <code>str</code> غير محددة.
</p>

<p>
	يمرّر السطر 4 عنصرًا مؤقّتًا إلى مُعامل الإسناد الخاص بـ <code>‎std::string‎</code>، الذي له تحميل زائد يأخذ <code>std::string&amp;&amp;‎</code>، ويكون التعبير <code>std::string("new value")‎</code> تعبيرًا يمينيًا (على وجه التحديد من الفئة prvalue)، لذا قد يستدعي التحميل الزائد. وعليه سيُنقل العنصر المؤقّت إلى <code>‎str‎</code> مع استبدال المحتويات غير المُحدّدة بمحتويات محدّدة.
</p>

<p>
	ينشئ السطر 5 مرجعًا يمينيًا مُسمّى (named rvalue reference) يحمل الاسم <code>‎str_ref‎</code> ويشير إلى <code>‎str‎</code>، وهنا تصبح فئات القيمة مُربكة. فرغم أن <code>‎str_ref‎</code> ستكون مرجعًا يمينيًّا يشير إلى <code>‎std::string‎</code>، إلا أن فئة قيمة التعبير <code>‎str_ref‎</code> ليست يمينيّة بل يسارية، ولهذا لا يمكن للمرء استدعاء مُنشئ النقل الخاص بـ <code>‎std::string‎</code> مع التعبير <code>‎str_ref‎</code>. ولنفس السبب فإن السطر 6 ينسخ قيمة <code>‎str‎</code> إلى <code>‎test3‎</code>. وإذا أردنا نقله، سيتعيّن علينا توظيف <code>‎std::move‎</code> مرّة أخرى.
</p>

<h2>
	القيمة المرتحلة xvalue
</h2>

<p>
	التعابير من فئة القيمة المرتحلة xvalue (أو eXpiring value) هي تعابير ذات هوية تمثّل كائنات يمكن النقل منها ضمنيًا. وفكرتها بشكل عام هي أنّ الكائنات التي تمثّلها هذه التعبيرات هي على وشك أن تُدمَّر، وبالتالي فإنّ النقل منها ضمنيًا سيكون مقبولًا.
</p>

<p>
	انظر الأمثلة التالية على ذلك:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7589_9" style="">
<span class="kwd">struct</span><span class="pln"> X
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> n</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">extern</span><span class="pln"> X x</span><span class="pun">;</span><span class="pln">
</span><span class="lit">4</span><span class="pun">;</span><span class="pln">    </span><span class="com">// prvalue: ليس لديها هوية</span><span class="pln">
x</span><span class="pun">;</span><span class="pln">    </span><span class="com">// lvalue</span><span class="pln">
x</span><span class="pun">.</span><span class="pln">n</span><span class="pun">;</span><span class="pln">    </span><span class="com">// lvalue</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span><span class="pln">    </span><span class="com">// xvalue</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="pln">X</span><span class="pun">&amp;&gt;(</span><span class="pln">x</span><span class="pun">);</span><span class="pln">    </span><span class="com">// lvalue</span><span class="pln">
X
</span><span class="pun">{</span><span class="pln">
    </span><span class="lit">4</span><span class="pln">
</span><span class="pun">};</span><span class="pln">    </span><span class="com">// prvalue: ليس لها هوية</span><span class="pln">
X
</span><span class="pun">{</span><span class="pln">
    </span><span class="lit">4</span><span class="pln">
</span><span class="pun">}.</span><span class="pln">n</span><span class="pun">;</span><span class="pln">    </span><span class="com">// xvalue: ليس لها هوية وتشير إلى موارد يمكن إعادة استخدامها</span></pre>

<h2>
	تعبيرات القيمة اليمينية الخالصة prvalue
</h2>

<p>
	تعبير القيمة اليمينيّة الخالصة prvalue (أو pure-rvalue) هي تعبيرات تفتقر إلى الهوية، ويُستخدم تقييمها عادة لتهيئة كائن يمكن نقله ضمنيًا. هذه بعض الأمثلة على ذلك:
</p>

<ul>
<li>
		التعبيرات التي تمثّل كائنات مؤقّتة، مثل <code>‎std::string("123")‎</code>.
	</li>
	<li>
		استدعاء دالة لا تعيد مرجعًا.
	</li>
	<li>
		كائن حرفي (باستثناء السلاسل النصية الحرفية - إذ أنها يسارية)، مثل <code>‎1‎</code> أو <code>‎true‎</code> أو <code>‎0.5f‎</code> أو <code>‎'a'‎</code>.
	</li>
	<li>
		<a data-ss1617023044="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-39-%D8%AF%D9%88%D8%A7%D9%84-%D9%84%D8%A7%D9%85%D8%AF%D8%A7-lambdas-%D9%81%D9%8A-cpp-r960/" rel="">تعبيرات لامدا</a>.
	</li>
</ul>
<p>
	لا يمكن تطبيق معامل العنونة (addressof operator) المُضمّن (<code>‎&amp;‎</code>) على هذه التعبيرات.
</p>

<h2>
	تعبيرات القيمة اليسارية lvalue
</h2>

<p>
	التعبيرات اليسارية lvalue هي تعبيرات ذات هويّة لكن لا يمكن النقل منها ضمنيًا، وتشمل التعبيرات التي تتألّف من اسم متغيّر واسم دالّة والتعبيرات التي تستخدمها مُعاملات التحصيل (dereference) المُضمّنة والتعبيرات التي تشير إلى مراجع يسارية.
</p>

<p>
	تكون القيمة اليسارية عادة مجرّد اسم، لكن يمكن أن تأتي بأشكال أخرى أيضًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7589_11" style="">
<span class="kwd">struct</span><span class="pln"> X
</span><span class="pun">{</span><span class="pln"> </span><span class="pun">…</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
X x</span><span class="pun">;</span><span class="pln">    </span><span class="com">// قيمة يسارية x</span><span class="pln">
X</span><span class="pun">*</span><span class="pln"> px </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">x</span><span class="pun">;</span><span class="pln">  </span><span class="com">// px is an lvalue </span><span class="pln">
</span><span class="pun">*</span><span class="pln">px </span><span class="pun">=</span><span class="pln"> X </span><span class="pun">{};</span><span class="pln">    </span><span class="com">// قيمة يمينيّة خالصة X{}  هي قيمة يسارية، و *px </span><span class="pln">
X</span><span class="pun">*</span><span class="pln"> foo_ptr</span><span class="pun">();</span><span class="pln">   </span><span class="com">//  قيمة يمينيّة خالصة foo_ptr() </span><span class="pln">
X </span><span class="pun">&amp;</span><span class="pln">foo_ref</span><span class="pun">();</span><span class="pln">    </span><span class="com">// قيمة يسارية foo_ref() </span></pre>

<p>
	في حين أنّ معظم الكائنات الحرفية (على سبيل المثال <code>‎4‎</code>، <code>‎'x'‎</code>) هي تعبيرات يمينية خالصة، إلا أن السلاسل النصية الحرفية يسارية.
</p>

<h2>
	تعبيرات القيم اليسارية المُعمّمة glvalue
</h2>

<p>
	تعابير القيم اليسارية المُعمّمة glvalue (أو "generalized lvalue") هي التعابير التي ليس لها هوية بغض النظر عما إذا كان يمكن النقل منها أم لا.
</p>

<p>
	وتشمل هذه الفئة تعبيرات القيم اليسارية (التعبيرات التي لها هوية ولكن لا يمكن النقل منها)، وتعبيرات القيمة المرتحلة xvalues (التعبيرات التي لها هوية، ويمكن النقل منها). بالمقابل، فهي لا تشمل القيم اليمينيةّ الخالصة prvalues (تعبيرات بدون هوية).
</p>

<p>
	وإذا كان لتعبيرٍ ما اسم، فإنّّه يساريّ معمَّم glvalue:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7589_13" style="">
<span class="kwd">struct</span><span class="pln"> X </span><span class="pun">{</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> n</span><span class="pun">;</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
X foo</span><span class="pun">();</span><span class="pln">

X x</span><span class="pun">;</span><span class="pln">

x</span><span class="pun">;</span><span class="pln">  
std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span><span class="pln"> 

foo</span><span class="pun">();</span><span class="pln">  
X </span><span class="pun">{};</span><span class="pln">   
X </span><span class="pun">{}.</span><span class="pln">n</span><span class="pun">;</span><span class="pln">    </span></pre>

<p>
	في الشيفرة السابقة:
</p>

<ul>
<li>
		<code>x</code> له اسم، وعليه يكون يساريًا معمَّمًا.
	</li>
	<li>
		<code>(std::move(x</code> له اسم بما أننا ننقل من <code>x</code>، وعليه يكون قيمة يسارية معمَّمة <code>glvalue</code> لكن بما أننا نستطيع النقل منها فتكون قيمة مرتحلة وليست يسارية.
	</li>
	<li>
		<code>()foo</code> ليس له اسم، فهو يميني خالص، وليس يساريا معمَّمًا.
	</li>
	<li>
		<code>{} X</code> قيمة مؤقتة ليس لها اسم، لذا فالتعبير يميني خالص، وليس يساريا معمَّمًا.
	</li>
	<li>
		<code>X {}.n</code> له اسم، لذا فهو يساري معمم، كما يمكن النقل منه، لذا فهو مرتحل وليس يساريًا معمَّمًا.
	</li>
</ul>
<p>
	هذا الدرس جزء من <a data-ss1617023044="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 74: Value Categories من كتاب <a data-ss1617023044="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">969</guid><pubDate>Sat, 29 Aug 2020 18:08:00 +0000</pubDate></item><item><title>&#x62F;&#x648;&#x627;&#x644; &#x644;&#x627;&#x645;&#x62F;&#x627; Lambdas &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%AF%D9%88%D8%A7%D9%84-%D9%84%D8%A7%D9%85%D8%AF%D8%A7-lambdas-%D9%81%D9%8A-cpp-r960/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_10/39.png.a5be6faed13529de8e0685e4ed008a75.png.101b177dea0bcf5ca54af4f58884e821.png" /></p>

<h2>
	ما هي تعابير لامدا؟
</h2>

<p>
	توفّر دوال لامدا طريقة موجزة لإنشاء كائنات دوالّ بسيطة، وتعبير لامدا هو قيمة يمينية خالصة (prvalue) تُنتجُ كائنَ تغليف (closure)، والذي يتصرف ككائن دالة.
</p>

<p>
	نشأ الاسم "تعبير لامدا" (lambda expression) عن علم حسابيات اللامدا (lambda calculus)، وهو شكل رياضي اختُرِع في الثلاثينيات من قِبل Alonzo Church للإجابة عن بعض الأسئلة المتعلقة بالمنطق والحوسبيّات (computability)، وقد شكّلت حسابيات لامدا أساس لغة LISP، وهي لغة برمجة وظيفية.
</p>

<p>
	مقارنة بحسابيات لامدا و LISP، فإنّّ تعبيرات لامدا في C++‎ تشترك معها في أنّها غير مسمّاة، وأنّها تلتقط المتغيّرات الموجودة في السياق المحيط، لكنّها تفتقر إلى القدرة على العمل على الدوال أو إعادتها.
</p>

<p>
	وغالبًا ما تُستخدَم دوال لامدا كوسائط للدوالّ التي تأخذ كائنًا قابلاً للاستدعاء، وذلك غالبًا أبسط من إنشاء دالة مُسمّاة، والتي لن تُستخدَم إلا عند تمريرها كوسيط، وتعبيرات لامدا مفضّلة في مثل هذه الحالات، لأنّها تسمح بتعريف الدوّال ضمنيًا.
</p>

<p>
	يتألف تعبير لامدا عادة من ثلاثة أجزاء: قائمة الالتقاط <code>‎[]‎</code>، وقائمة المعاملات الاختيارية <code>‎()‎</code>، والمتن <code>‎{}‎</code>، وكلها يمكن أن تكون فارغة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_7" style="">
<span class="pun">[]()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">    </span><span class="com">// تعبير لامدا فارغ لا يعيد أي شيء.</span></pre>

<h3>
	قائمة الالتقاط (Capture list)
</h3>

<p>
	تمثّل <code>‎[]‎</code> قائمة الالتقاط. لا يمكن الوصول إلى متغيّرات النطاق المحيط عبر تعبير لامدا افتراضيًا، ويكون المتغير متاحًا بمجرد التقاطه داخل تعبير لامدا سواء كنسخة أو مرجع، وتصبح المتغيرات الملتقطة جزءًا من لامدا، ولا يلزم تمريرها عند استدعاء لامدا، على عكس وسائط الدوال.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_9" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">    </span><span class="com">// تعريف متغير عددي صحيح</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> f </span><span class="pun">=[]()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> a </span><span class="pun">*</span><span class="pln"> </span><span class="lit">9</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">    </span><span class="com">// Error: 'a' cannot be accessed</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> f </span><span class="pun">=[</span><span class="pln">a</span><span class="pun">]()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> a </span><span class="pun">*</span><span class="pln"> </span><span class="lit">9</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">    </span><span class="com">// بالقيمة  'a' تم التقاط</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> f </span><span class="pun">=[&amp;</span><span class="pln"> a</span><span class="pun">]()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> a</span><span class="pun">++;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">    </span><span class="com">// بالمرجع  'a' تم التقاط</span><span class="pln">
</span><span class="com">//     a ملاحظة: المبرمج ليس مسؤولا عن ضمان ألا تُدمَّر</span><span class="pln">
</span><span class="com">//        قبل استدعاء لامدا</span><span class="pln">

</span><span class="kwd">auto</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> f</span><span class="pun">();</span><span class="pln">    </span><span class="com">// من دالة الالتقاط ولم تُمرّر هنا a استدعاء دالة لامدا، تم أخذ</span></pre>

<h3>
	قائمة المعاملات
</h3>

<p>
	تمثّل <code>‎()‎</code> قائمة المعاملات، وهي تماثل قائمة المعاملات في الدوال العادية، ويمكن حذف الأقواس إذا لم يأخذ تعبير لامدا أيّ وسائط، إلا إذا كنت بحاجة إلى جعل تعبير لامدا قابلًا للتغيير <code>‎mutable‎</code>. يُعدُّ تعبيرا لامدا التاليان متكافئين:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_11" style="">
<span class="kwd">auto</span><span class="pln"> call_foo </span><span class="pun">=[</span><span class="pln">x</span><span class="pun">]()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    x</span><span class="pun">.</span><span class="pln">foo</span><span class="pun">();</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> call_foo2 </span><span class="pun">=[</span><span class="pln">x</span><span class="pun">]</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    x</span><span class="pun">.</span><span class="pln">foo</span><span class="pun">();</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 14</strong>
</p>

<p>
	تستطيع قائمةُ المعاملات أن تستخدم النوعَ النائب (placeholder type)‏ <code>‎auto‎</code> بدلاً من الأنواع الفعلية، وهذا يجعل الوسيط يتصرّف كمُعامل قالب لقالب دالة. تعبيرات لامدا التالية متكافئة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_13" style="">
<span class="kwd">auto</span><span class="pln"> sort_cpp11 </span><span class="pun">=[](</span><span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;::</span><span class="pln">const_reference lhs</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">vector</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;::</span><span class="pln">const_reference rhs</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> lhs </span><span class="pun">&lt;</span><span class="pln"> rhs</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> sort_cpp14 </span><span class="pun">=[](</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">lhs</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">rhs</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> lhs </span><span class="pun">&lt;</span><span class="pln"> rhs</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<h3>
	متن الدالة
</h3>

<p>
	القوسان المعقُوصان <code>‎{}‎</code> يحتويان على متن تعبير لامدا، ويُماثل متن الدوال العادية.
</p>

<h3>
	استدعاء دالة لامدا
</h3>

<p>
	يعيد تعبير لامدا مغلِّفًا أو غلافًا (closure)، ويمكن استدعاؤه باستخدام الصيغة <code>‎operator()‎</code> (كما هو الحال مع الدوال العادية):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_15" style="">
<span class="typ">int</span><span class="pln"> multiplier </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> timesFive </span><span class="pun">=[</span><span class="pln">multiplier</span><span class="pun">](</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> a </span><span class="pun">*</span><span class="pln"> multiplier</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">out </span><span class="pun">&lt;&lt;</span><span class="pln"> timesFive</span><span class="pun">(</span><span class="lit">2</span><span class="pun">);</span><span class="pln">    </span><span class="com">// 10</span><span class="pln">
multiplier </span><span class="pun">=</span><span class="pln"> </span><span class="lit">15</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">out </span><span class="pun">&lt;&lt;</span><span class="pln"> timesFive</span><span class="pun">(</span><span class="lit">2</span><span class="pun">);</span><span class="pln">    </span><span class="com">// 2 *5 == 10</span></pre>

<h3>
	نوع القيمة المعادة
</h3>

<p>
	افتراضيًا، يُستنبَط نوع القيمة المُعادة لتعبير لامدا تلقائيًا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_19" style="">
<span class="pun">[]()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	في هذه الحالة، نوع القيمة المُعادة هو <code>‎bool‎</code>، يمكنك أيضًا تعريف نوع القيمة المُعادة يدويًا باستخدام الصياغة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_21" style="">
<span class="pun">[]()-&gt;</span><span class="kwd">bool</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<h3>
	دوال لامدا القابلة للتغيير (Mutable Lambda)
</h3>

<p>
	الكائنات المُلتقطة بالقيمة في دوال لامدا تكون افتراضيًا غير قابلة للتغيير (immutable)، وذلك لأنّ المُعامل <code>‎operator()‎</code> الخاصّ بالكائن المغلّف المُنشأ ثابت (<code>‎const‎</code>) افتراضيًا. في المثال التالي، سيفشل التصريف لأن ++C ستحاول محاكاة حالة تعبير لامدا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_23" style="">
<span class="kwd">auto</span><span class="pln"> func </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">c </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">](){++</span><span class="pln">c</span><span class="pun">;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> c</span><span class="pun">;};</span></pre>

<p>
	يمكن السماح بالتعديل باستخدام الكلمة المفتاحية <code>‎mutable‎</code>، والتي تجعل المُعامل <code>‎operator()‎</code> غير ثابت <code>‎const‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_25" style="">
<span class="kwd">auto</span><span class="pln"> func </span><span class="pun">=[</span><span class="pln">c </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">]()</span><span class="pln"> </span><span class="kwd">mutable</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="pun">++</span><span class="pln">c</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> c</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	إذا اسُتخدِم مع نوع القيمة المُعادة، فينبغي وضع <code>‎mutable‎</code> قبله.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_27" style="">
<span class="kwd">auto</span><span class="pln"> func </span><span class="pun">=[</span><span class="pln">c </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">]()</span><span class="pln"> </span><span class="kwd">mutable</span><span class="pun">-&gt;</span><span class="typ">int</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="pun">++</span><span class="pln">c</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> c</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> c</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	انظر المثال التالي لتوضيح فائدة لامدا:
</p>

<p>
	<strong>الإصدار &lt; C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_29" style="">
<span class="com">// كائن دالي عام لأجل المقارنة</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> islessthan
</span><span class="pun">{</span><span class="pln">
    islessthan</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> threshold</span><span class="pun">):</span><span class="pln"> _threshold</span><span class="pun">(</span><span class="pln">threshold</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

    </span><span class="kwd">bool</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">()(</span><span class="typ">int</span><span class="pln"> value</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> value </span><span class="pun">&lt;</span><span class="pln"> _threshold</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> _threshold</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// التصريح عن متجهة</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> arr</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> vec</span><span class="pun">(</span><span class="pln">arr</span><span class="pun">,</span><span class="pln"> arr </span><span class="pun">+</span><span class="pln"> </span><span class="lit">5</span><span class="pun">);</span><span class="pln">
</span><span class="com">// إيجاد عدد أصغر من مُدخَل مُعطى - على افتراض أنه سيكون مُدخلا إلى دالة</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> threshold </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pun">::</span><span class="typ">iterator</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">find_if</span><span class="pun">(</span><span class="pln">vec</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> vec</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> islessthan</span><span class="pun">(</span><span class="pln">threshold</span><span class="pun">));</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_31" style="">
<span class="com">// التصريح عن متجهة</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> vec
</span><span class="pun">{</span><span class="pln">
    </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// إيجاد عدد أصغر من مُدخَل مُعطى - على افتراض أنه سيكون مُدخلا إلى دالة</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> threshold </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">find_if</span><span class="pun">(</span><span class="pln">vec</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> vec</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> </span><span class="pun">[</span><span class="pln">threshold</span><span class="pun">](</span><span class="typ">int</span><span class="pln"> value</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> value </span><span class="pun">&lt;</span><span class="pln"> threshold</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">});</span></pre>

<p>
	يمكننا تلخيص ما سبق بالجدول التالي:
</p>
<style type="text/css">
table {
    width: 100%;
}

thead {
    vertical-align: middle;
    text-align: center;
}

td, th {
    border: 1px solid #dddddd;
    text-align: right;
    padding: 8px;
    text-align: inherit;

}
tr:nth-child(even) {
    background-color: #dddddd;
}</style>
<table>
<thead><tr>
<th>
				المعامل
			</th>
			<th>
				التفاصيل
			</th>
		</tr></thead>
<tbody>
<tr>
<td>
				default-capture الالتقاط الافتراضي
			</td>
			<td>
				يحدّد كيفيّة التقاط جميع المتغيّرات غير المدرجة، قد يكون عبر <code>‎=‎</code> (التقاطًا بالقيمة) أو عبر <code>‎&amp;‎</code> (التقاطا بالمرجع). وفي حال حذفها، سيتعذّر الوصول إلى المتغيّرات غير المدرجة ضمن متن لامدا. كما يجب أن يسبق default- capture المعاملُ capture-list.
			</td>
		</tr>
<tr>
<td>
				capture-list لائحة الالتقاط
			</td>
			<td>
				يحدّد كيف يمكن الوصول إلى المتغيّرات المحلية داخل متن لامدا، تُلتقط المتغيّرات التي ليست لها سابقة (prefix) بالقيمة (by value) بينما تُلتقط المتغيّرات المسبوقة بـ <code>‎&amp;‎</code> بالمرجع. يمكن استخدام <code>‎this‎</code> في توابع الأصناف لجعل جميع أعضاء الكائن الذي يشير إليه في المتناول عبر المرجع. ولا يمكن الوصول إلى المتغيّرات غير المدرجة في القائمة إلا إذا كانت القائمة مسبوقة بـ default-capture.
			</td>
		</tr>
<tr>
<td>
				argument-list قائمة الوسائط
			</td>
			<td>
				يحدّد وسائط دالّة لامدا.
			</td>
		</tr>
<tr>
<td>
				mutable
			</td>
			<td>
				(اختياري) عادة ما تكون المتغيّرات الملتقطة بالقيمة ثابتة (<code>‎const‎</code>). وستكون غير ثابتة عند تحديد <code>‎mutable‎</code>. وسيُحتفظ بالتغييرات على تلك المتغيّرات بين الاستدعاءات.
			</td>
		</tr>
<tr>
<td>
				throw-specification رفع الاعتراضات
			</td>
			<td>
				(اختياري) يحدّد سلوك رفع الاعتراضات في دالّة لامدا، مثل: <code>‎noexcept‎</code> أو <code>‎throw‎</code>‏ (<code>std::exception</code>).
			</td>
		</tr>
<tr>
<td>
				attributes السمات
			</td>
			<td>
				(اختياري) سمات دالّة لامدا. على سبيل المثال، إذا كان متن لامدا يلقي دائمًا اعتراضًا، فيمكن استخدام <code>‎[[noreturn]]‎</code>.
			</td>
		</tr>
<tr>
<td>
				نوع القيمة المعادة
			</td>
			<td>
				(اختياري) يحدّد نوع القيمة المُعادة من دالّة لامدا. وهي ضرورية في الحالات التي لا يكون بمقدور المٌصرّف فيها تخمين نوع القيمة المعادة.
			</td>
		</tr>
<tr>
<td>
				lambda-body متن لامدا
			</td>
			<td>
				الكتلة التي تحتوي تنفيذ لامدا.
			</td>
		</tr>
</tbody>
</table>
<h2>
	تحديد نوع القيمة المُعادة
</h2>

<p>
	بالنسبة لدوال لامدا التي تحتوي عبارة return واحدة فقط، أو عدّة عبارات return من نفس النوع، فيمكن للمصرّف أن يستنتج نوع القيمة المُعادة. انظر المثال التالي الذي يعيد قيمة بوليانية لأن "10 &lt; value" هي قيمة بوليانية.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_33" style="">
<span class="kwd">auto</span><span class="pln"> l </span><span class="pun">=[](</span><span class="typ">int</span><span class="pln"> value</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> value </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	بالنسبة لدوال لامدا التي لها عدّة عبارات return من أنواع مختلفة، فلا يمكن للمصرّف أن يستنتج نوع القيمة المُعادة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_35" style="">
<span class="com">// error: return types must match if lambda has unspecified return type</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> l </span><span class="pun">=[](</span><span class="typ">int</span><span class="pln"> value</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">value </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">else</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">1.5</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	في هذه الحالة، يجب عليك تحديد نوع القيمة المُعادة بشكل صريح:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_37" style="">
<span class="com">// 'double' حُدِّد نوع القيمة المعادة بـ</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> l </span><span class="pun">=[](</span><span class="typ">int</span><span class="pln"> value</span><span class="pun">)-&gt;</span><span class="kwd">double</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">value </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">else</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">1.5</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	تطابق هذه القواعدُ قواعدَ استنتاج نوع <code>‎auto‎</code>، ولا تعيد دوال لامدا التي لم يُصرّح بنوع قيمتها المُعادة صراحة مراجعًا أبدًا، لذا إذا كنت تودّ إعادة نوع مرجعي (reference type)، فيجب تحديده بشكل صريح: تعيد <code>copy</code> في المثال التالي قيمة من نوع <code>&amp;X</code> لذا تنسخ المدخلات:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_39" style="">
<span class="kwd">auto</span><span class="pln"> copy </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[](</span><span class="pln">X</span><span class="pun">&amp;</span><span class="pln"> x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> x</span><span class="pun">;</span><span class="pln"> </span><span class="pun">};</span><span class="pln">   </span></pre>

<p>
	لا يحدث نسخ لأن <code>ref</code> في المثال التالي ستعيد قيمة من نوع <code>&amp;X</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_41" style="">
<span class="kwd">auto</span><span class="pln"> ref </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[](</span><span class="pln">X</span><span class="pun">&amp;</span><span class="pln"> x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> X</span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> x</span><span class="pun">;</span><span class="pln"> </span><span class="pun">};</span><span class="pln">   </span></pre>

<h2>
	الالتقاط بالقيمة Capture by value
</h2>

<p>
	إن حدّدتَ اسم المتغيّر في قائمة الالتقاط فإنّّ تعبير لامدا سيلتقطُه بالقيمة، هذا يعني أنّ نوع المغلِّف المُنشأ لتعبير لامدا سيخزّن نسخة من المتغيّر، وهذا يتطّلب أيضًا أن يكون نوع المتغيّر قابلاً للنسخ:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_43" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">[</span><span class="pln">a</span><span class="pun">]()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">    </span><span class="com">// بالقيمة 'a' تم التقاط</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	<strong>الإصدار &lt; C++‎ 14</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_45" style="">
<span class="kwd">auto</span><span class="pln"> p </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">unique_ptr</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;(...);</span><span class="pln">
</span><span class="pun">[</span><span class="pln">p</span><span class="pun">]()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// Compile error; `unique_ptr` is not copy-constructible</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> p</span><span class="pun">-&gt;</span><span class="pln">createWidget</span><span class="pun">();</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	من C++‎ 14 وصاعدًا، من الممكن تهيئة المتغيّرات على الفور، وهذا يسمح بالتقاط "أنواع النقل فقط" في لامدا.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 14</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_47" style="">
<span class="kwd">auto</span><span class="pln"> p </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_unique</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(...);</span><span class="pln">
</span><span class="pun">[</span><span class="pln">p </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">p</span><span class="pun">)]()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> p</span><span class="pun">-&gt;</span><span class="pln">createWidget</span><span class="pun">();</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	رغم أنّ دوال لامدا يمكن أن تلتقط المتغيّرات بالقيمة عندما تُمرّر باسمائها، إلّا أنّ تلك المتغيّرات لا يمكن تعديلها في متن لامدا افتراضيًا، وذلك لأنّ نوع المغلّف يضع متن لامدا في تصريح من الشكل <code>‎operator() const‎</code>.
</p>

<p>
	وتُطبَّق <code>‎const‎</code> على محاولات الوصول إلى المتغيّرات العضوية (member variables) في نوع المغلّف، والمتغيّرات المُلتقطة التي هي أعضاء في المغلّف (على خلاف المتوقّع):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_49" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">[</span><span class="pln">a</span><span class="pun">]()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">    </span><span class="com">// غير جائز</span><span class="pln">
    </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">a</span><span class="pun">)</span><span class="pln"> a1 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
    a1 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">    </span><span class="com">// جائز</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	لإزالة <code>‎const‎</code>، يجب عليك وضع الكلمة المفتاحية <code>‎mutable‎</code> في تعبير لامدا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_51" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">[</span><span class="pln">a</span><span class="pun">]()</span><span class="pln"> </span><span class="kwd">mutable</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">    </span><span class="com">// 'a' يمكن الآن تعديل</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	نظرًا لأنّ <code>‎a‎</code> التُقِطت بالقيمة، فإنّّ أيّ تعديلات تُجرى عن طريق استدعاء تعبير لامدا لن تؤثر على <code>‎a‎</code>، ولقد نُسخِت قيمة <code>‎a‎</code> في تعبير لامدا عند إنشائه، لذلك فإنّ نسخة <code>‎a‎</code> في تعبير لامدا مختلفة عن المتغيّر <code>‎a‎</code> الخارجي.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_53" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> plus5Val </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">a</span><span class="pun">]</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">void</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> plus5Ref </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[&amp;</span><span class="pln">a</span><span class="pun">]</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">void</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="kwd">return</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">7</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> a </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", value "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> plus5Val</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", reference "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> plus5Ref</span><span class="pun">()</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
</span><span class="com">// "7, value 10, reference 12"</span></pre>

<h2>
	تعبيرات لامدا الذاتية الاستداعاء Recursive lambdas
</h2>

<p>
	لنفترض أنّنا نرغب في كتابة خوارزمية اقليدس للقاسم المشترك الأكبر <code>‎gcd()‎</code> على شكل تعبير لامدا. أولا، سنكتبها على شكل دالة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_55" style="">
<span class="typ">int</span><span class="pln"> gcd</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> b </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> a </span><span class="pun">:</span><span class="pln"> gcd</span><span class="pun">(</span><span class="pln">b</span><span class="pun">,</span><span class="pln"> a</span><span class="pun">%</span><span class="pln">b</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تعبيرات لامدا لا يمكن أن تكون ذاتية الاستدعاء، لأنها غير قادرة على استدعاء نفسها، فلامدا ليس لها اسم، واستخدام <code>‎this‎</code> داخل متن لامدا إنّما يشير إلى <code>‎this‎</code> المُلتقَط (بافتراض أنّ تعبير لامدا مُنشأ في متن دالة تابعة، وإلا فسيُطلق خطأ)، إذن كيف نحلّ هذه المشكلة؟
</p>

<h3>
	استخدام std::function
</h3>

<p>
	يمكننا جعل تعبير لامدا يحصل على مرجع إلى كائن <code>‎std::function‎</code> لم يُنشأ بعد:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_57" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">function</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">(</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">)&gt;</span><span class="pln"> gcd </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[&amp;](</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">){</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> b </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> a </span><span class="pun">:</span><span class="pln"> gcd</span><span class="pun">(</span><span class="pln">b</span><span class="pun">,</span><span class="pln"> a</span><span class="pun">%</span><span class="pln">b</span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	هذا سيعمل بدون مشاكل، ولكن ينبغي ألّا تستخدم هذه الطريقة إلّا لُمامًا، إذ أنّها بطيئة (لأنّنا نستخدم محو الأنواع - type erasure - بدلاً من استدعاء الدالّة المباشرة)، كما أنّها هشّة (نسخ <code>‎gcd‎</code> أو إعادة <code>‎gcd‎</code> سيكسر الشيفرة لأنّ تعبير لامدا يشير إلى الكائن الأصلي)، ولن تعمل مع دوال لامدا العامة.
</p>

<h3>
	استخدام مؤشرين ذكيين
</h3>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_59" style="">
<span class="kwd">auto</span><span class="pln"> gcd_self </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_shared</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">unique_ptr</span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">function</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">(</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">)&gt;</span><span class="pln"> </span><span class="pun">&gt;&gt;();</span><span class="pln">
</span><span class="pun">*</span><span class="pln">gcd_self </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_unique</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">function</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">(</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">)&gt;&gt;(</span><span class="pln">
</span><span class="pun">[</span><span class="pln">gcd_self</span><span class="pun">](</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">){</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> b </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> a </span><span class="pun">:</span><span class="pln"> </span><span class="pun">(**</span><span class="pln">gcd_self</span><span class="pun">)(</span><span class="pln">b</span><span class="pun">,</span><span class="pln"> a</span><span class="pun">%</span><span class="pln">b</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	هذا يضيف الكثير من الأعمال غير المباشرة (ما يؤدّي إلى زيادة الحِمل)، ولكن يمكن نسخه/إعادته، كما أنّ جميع النسخ تشترك في الحالة، وهذا يتيح لك إعادة تعبير لامدا، وهذا الحل أفضل من الحل المذكور أعلاه.
</p>

<h3>
	استخدام Y-combinator
</h3>

<p>
	باستخدام بِنية صغيرة مُساعِدة، يمكننا حل جميع هذه المشاكل:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_61" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> F</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> y_combinator
    </span><span class="pun">{</span><span class="pln">
        F f</span><span class="pun">;</span><span class="pln">    </span><span class="com">// لامدا ستُخزَّن هنا</span><span class="pln">
        </span><span class="com">// مسبق operator() عامل</span><span class="pln">
        </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="typ">Args</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
            </span><span class="kwd">decltype</span><span class="pun">(</span><span class="kwd">auto</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">()(</span><span class="typ">Args</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">...</span><span class="pln">args</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
            </span><span class="pun">{</span></pre>

<p>
	ستمرر نفسها هنا إلى <code>f</code> ثم تمرر الوسائط، ويجب أن تأخذ لامدا الوسيط الأول كـ <code>auto&amp;&amp; recurse</code> أو نحوه، نتابع المثال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_63" style="">
<span class="pln">             </span><span class="kwd">return</span><span class="pln"> f</span><span class="pun">(*</span><span class="kwd">this</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="typ">Args</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">args</span><span class="pun">)...);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="com">// :دالة مساعِدة تستنبط نوع لامدا</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> F</span><span class="pun">&gt;</span><span class="pln">
    y_combinator</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="typ">decay_t</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> F</span><span class="pun">&gt;&gt;</span><span class="pln"> make_y_combinator</span><span class="pun">(</span><span class="pln">F </span><span class="pun">&amp;&amp;</span><span class="pln"> f</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="pln">F</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">f</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">};</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="com">// ( `make_` هناك حلول أفضل من C++17 تذكر أنّ في )</span></pre>

<p>
	يمكننا تنفيذ <code>‎gcd‎</code> على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_65" style="">
<span class="kwd">auto</span><span class="pln"> gcd </span><span class="pun">=</span><span class="pln"> make_y_combinator</span><span class="pun">(</span><span class="pln">
</span><span class="pun">[](</span><span class="kwd">auto</span><span class="pun">&amp;&amp;</span><span class="pln"> gcd</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">){</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> b </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> a </span><span class="pun">:</span><span class="pln"> gcd</span><span class="pun">(</span><span class="pln">b</span><span class="pun">,</span><span class="pln"> a</span><span class="pun">%</span><span class="pln">b</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">);</span></pre>

<p>
	<code>‎y_combinator‎</code> هو أحد مفاهيم حسابيّات لامدا، ويتيح لك العمل بالذاتية دون الحاجة إلى تسمية الدالة، وهذا هو بالضبط ما ينقصنا في دوال لامدا. تستطيع إنشاء تعبير لامدا يأخذ "recurse" كوسيط أوّل، وعندما تريد استخدام الذاتية، يمكنك تمرير الوسائط إلى recurse.
</p>

<p>
	ويعيد <code>‎y_combinator‎</code> بعد ذلك كائن دالة يستدعي تلك الدالّة مع وسائطها، ولكن بكائن "recurse" المناسب (أي <code>‎y_combinator‎</code> نفسه) كوسيط أوّل، ويوجِّه بقية الوسائط التي مرّرتها إلى <code>‎y_combinator‎</code> إلى تعبير لامدا على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_67" style="">
<span class="kwd">auto</span><span class="pln"> foo </span><span class="pun">=</span><span class="pln"> make_y_combinator</span><span class="pun">(</span><span class="pln"> </span><span class="pun">[&amp;](</span><span class="kwd">auto</span><span class="pun">&amp;&amp;</span><span class="pln"> recurse</span><span class="pun">,</span><span class="pln"> some arguments</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// اكتب شيفرة تعالج بعض المعاملات</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	استدع <code>recurse</code> مع بعض الوسائط الأخرى عند الحاجة لتنفيذ الذاتية (Recursion)، وكذلك نحصل على الذاتية في لامدا دون أيّ قيود أو حِمل كبير.
</p>

<h2>
	الالتقاط الافتراضي Default capture
</h2>

<p>
	افتراضيًا، لا يمكن الوصول إلى المتغيّرات المحلية التي لم تُحدَّد بشكل صريح في قائمة الالتقاط من داخل متن تعبير لامدا، بيْد أنّه من الممكن ضمنيًا التقاط المتغيّرات المُسمّاة من قبل متن لامدا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_69" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
</span><span class="com">// التقاط افتراضي بالقيمة</span><span class="pln">
</span><span class="pun">[=]()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">;</span><span class="pln"> </span><span class="pun">};</span><span class="pln">    </span><span class="com">// بالقيمة a و b تم التقاط</span><span class="pln">
</span><span class="com">// الالتقاط الافتراضي بالمرجع</span><span class="pln">
</span><span class="pun">[&amp;]()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">;</span><span class="pln"> </span><span class="pun">};</span><span class="pln">    </span><span class="com">// بالمرجع a و b </span></pre>

<p>
	ما يزال بالإمكان القيام بالتقاط صريحٍ بجانب الالتقاط الافتراضي الضِّمني، سيعيد الالتقاط الصريح تعريف الالتقاط الافتراضي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_71" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="pun">[=,</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">b</span><span class="pun">]()</span><span class="pln"> 
</span><span class="pun">{</span><span class="pln">
    a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">   
    b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">   
</span><span class="pun">};</span></pre>

<p>
	في الشيفرة السابقة: لا تجوز <code>a = 2</code> لأن <code>a</code> ملتقطَة بالقيمة، وتعبير لامدا لا يقبل التغيير، أي ليس <code>mutable</code>، بينما تجوز <code>b = 2</code> لأن <code>b</code> ملتقَطة بالمرجع.
</p>

<h2>
	دوال لامدا في الأصناف والتقاط this
</h2>

<p>
	تُعدُّ تعبيرات لامدا الذي تم تقييمها في تابع ما صديقة للصّنف الذي ينتمي إليه ذلك التابع ضمنيًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_73" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Foo</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> val</span><span class="pun">):</span><span class="pln"> i</span><span class="pun">(</span><span class="pln">val</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

    </span><span class="com">// تعريف دالة تابعة</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Test</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">auto</span><span class="pln"> lamb </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[](</span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">foo</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> val</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="com">// (private) تعديل متغير عضو خاص</span><span class="pln">
            foo</span><span class="pun">.</span><span class="pln">i </span><span class="pun">=</span><span class="pln"> val</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">};</span></pre>

<p>
	يُسمح لـ <code>lamb</code> أن تصل إلى عضو خاص لأنها صديقة لـ <code>Foo</code>، نتابع المثال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_75" style="">
<span class="pln">        lamb</span><span class="pun">(*</span><span class="kwd">this</span><span class="pun">,</span><span class="pln"> </span><span class="lit">30</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	مثل هذه التعبيرات ليست صديقة لهذا الصنف فحسب، بل لها نفس إمكانيات الوصول التي يتمتّع بها الصنف الذي صُرِّح عنها فيه. كذلك يمكن لدَوال لامدا التقاط المؤشّر <code>‎this‎</code>، والذي يمثّل نُسخة الكائن الذي استُدعِيت الدالّة الخارجية عليه، عن طريق إضافة <code>‎this‎</code> إلى قائمة الالتقاط، انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_77" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Foo</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> val</span><span class="pun">):</span><span class="pln"> i</span><span class="pun">(</span><span class="pln">val</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

    </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Test</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// بالقيمة this التقاط المؤشر</span><span class="pln">
        </span><span class="kwd">auto</span><span class="pln"> lamb </span><span class="pun">=[</span><span class="kwd">this</span><span class="pun">](</span><span class="typ">int</span><span class="pln"> val</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            i </span><span class="pun">=</span><span class="pln"> val</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">};</span><span class="pln">

        lamb</span><span class="pun">(</span><span class="lit">30</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	عند التقاط <code>‎this‎</code>، يمكن لتعبير لامدا استخدام أسماء أعضاء الصنف الذي يحتويه كما لو كان في صنفه الحاوي، لذلك تُطبّق <code>‎this-&gt;‎</code> ضمنيًا على أولئك الأعضاء. يجب الانتباه إلى أنّ <code>‎this‎</code> تُلتقط بالقيمة، ولكن ليس بقيمة النوع، بل تُلتقَط بقيمة <code>‎this‎</code>، وهو مؤشّر، لهذا فإنّ تعبير لامدا لا يملك <code>‎this‎</code>، وإذا تجاوز عُمرُ تعبير لامدا عمرَ الكائن الذي أنشأه، فقد يصبح غير صالح.
</p>

<p>
	هذا يعني أيضًا أنّ لامدا يمكنها تعديل <code>‎this‎</code> حتى لو لم تكن قابلة للتغيير (<code>‎mutable‎</code>)، ذلك أنّ المؤشّر هو الذي يكون ثابتًا <code>‎const‎</code> وليس الكائن الذي يؤشّر إليه، إلا إن كان التابع الخارجي دالة ثابتة <code>‎const‎</code>.
</p>

<p>
	أيضًا، تذكّر أنّ كتل الالتقاط الافتراضية <code>‎[=]‎</code> و <code>‎[&amp;]‎</code> ستلتقط <code>‎this‎</code> ضمنيًا، وكلاهما سيلتقطَانه بقيمة المؤشّر، وفي الحقيقة، فمن الخطأ تحديد <code>‎this‎</code> في قائمة الالتقاط عند إعطاء قيمة افتراضية.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 17</strong>
</p>

<p>
	وتستطيع دوال لامدا التقاط نسخة من كائن <code>‎this‎</code> المُنشأ في وقت إنشاء تعبير لامدا، وذلك عن طريق إضافة <code>‎*this‎</code> إلى قائمة الالتقاط:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_79" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Foo</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> val</span><span class="pun">):</span><span class="pln"> i</span><span class="pun">(</span><span class="pln">val</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

    </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Test</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// التقاط نسخة من الكائن المُعطى من قبل المؤشر</span><span class="pln">
        </span><span class="kwd">auto</span><span class="pln"> lamb </span><span class="pun">=[*</span><span class="kwd">this</span><span class="pun">](</span><span class="typ">int</span><span class="pln"> val</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">mutable</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            i </span><span class="pun">=</span><span class="pln"> val</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">};</span><span class="pln">

        lamb</span><span class="pun">(</span><span class="lit">30</span><span class="pun">);</span><span class="pln">    </span><span class="com">// this-&gt;i لا تغيّر</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<h2>
	الالتقاط بالمرجع Capture by reference
</h2>

<p>
	إذا وضعت السابقة <code>‎&amp;‎</code> قبل اسم متغيّر محلي، فسيُلتقط المتغيّر بالمرجع، هذا يعني نظريًا أنّ نوع مُغلِّفِ لامدا سيكون له متغيّر مرجعي يُهيَّأُ كمرجع، وسيشير ذلك المرجع إلى المتغيّر المقابل الموجود خارج نطاق تعبير لامدا، وأيّ استخدام للمتغيّر في متن لامدا سوف يشير إلى المتغيّر الأصلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_81" style="">
<span class="com">// 'a' التصريح عن المتغير</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="com">// بالمرجع 'a' التصريح عن لامدا تلتقط</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> </span><span class="typ">set</span><span class="pln"> </span><span class="pun">=[&amp;</span><span class="pln"> a</span><span class="pun">]()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">set</span><span class="pun">();</span><span class="pln">
assert</span><span class="pun">(</span><span class="pln">a </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span></pre>

<p>
	الكلمة المفتاحية <code>‎mutable‎</code> ليست مطلوبة لأنّ <code>‎a‎</code> نفسها ليست ثابتة. والالتقاط بالمرجع يعني أنّ لامدا يجب ألا تخرج عن نطاق المتغيّرات التي تلتقطها، لذلك يمكنك استدعاء الدوال التي تأخذ دالّة، ولكن لا تستدع دالّة تخزّن لامدا خارج نطاق مراجعك، وكذلك لا تُعِد تعبير لامدا.
</p>

<h2>
	تعابير لامدا العامة النوع Generic lambdas
</h2>

<p>
	<strong>الإصدار ≥ C++‎ 14</strong>
</p>

<p>
	يمكن أن تأخذ دوال لامدا وسائط من أيّ نوع، هذا يسمح لهذه الدوال أن تكون أكثر عمومية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_83" style="">
<span class="kwd">auto</span><span class="pln"> twice </span><span class="pun">=[](</span><span class="kwd">auto</span><span class="pln"> x</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> x </span><span class="pun">+</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> twice</span><span class="pun">(</span><span class="lit">2</span><span class="pun">);</span><span class="pln">    </span><span class="com">// i == 4</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string s </span><span class="pun">=</span><span class="pln"> twice</span><span class="pun">(</span><span class="str">"hello"</span><span class="pun">);</span><span class="pln">    </span><span class="com">// s == "hellohello"</span></pre>

<p>
	طُبِّق هذا في C++‎ عبر جعل <code>‎operator()‎</code> <a data-ss1617023045="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-22-%D8%A7%D9%84%D8%AA%D8%AD%D9%85%D9%8A%D9%84-%D8%A7%D9%84%D8%B2%D8%A7%D8%A6%D8%AF-overloading-%D8%AA%D8%AD%D9%84%D9%8A%D9%84%D9%87-%D9%88%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D9%87-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D9%81%D9%8A-cpp-r934/" rel="">تزيد تحميل</a> دالّة قالب (template function)، انظر النوع التالي الذي له سلوك مكافئ لسلوك مُغلِّف لامدا أعلاه:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_85" style="">
<span class="kwd">struct</span><span class="pln"> _unique_lambda_type
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">auto</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">()(</span><span class="pln">T x</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> x </span><span class="pun">+</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	ليس بالضرورة أن تكون كل المعاملات عامة في تعبير لامدا غير المحدد أو العام (Generic lambda):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_87" style="">
<span class="pun">[](</span><span class="kwd">auto</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> y</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> x </span><span class="pun">+</span><span class="pln"> y</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هنا، تُستنبَط <code>‎x‎</code> بناءً على وسيط الدالّة الأوّل، بينما سيكون <code>‎y‎</code> دائمًا عددًا صحيحًا (<code>‎int‎</code>)، وقد تأخذ دوال لامدا العامَّة الوسائط بالمرجع أيضًا، وذلك باستخدام القواعد المعتادة لـ <code>‎auto‎</code> و <code>‎&amp;‎</code>، أما إن أُخذ وسيط عام كـ <code>‎auto&amp;&amp;‎</code>، فسيكون مرجعًا أماميًا (forwarding reference) يشير إلى الوسيط المُمرّر، وليس مرجعًا يمينِيّا (rvalue reference):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_89" style="">
<span class="kwd">auto</span><span class="pln"> lamb1 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[](</span><span class="typ">int</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln">x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="kwd">return</span><span class="pln"> x </span><span class="pun">+</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;};</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> lamb2 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[](</span><span class="kwd">auto</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln">x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="kwd">return</span><span class="pln"> x </span><span class="pun">+</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln">
lamb1</span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span><span class="pln">   
lamb2</span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span><span class="pln">   </span></pre>

<p>
	في الشيفرة السابقة، لا تجوز <code>(lamb1(x</code> لوجوب استخدام <code>std::move(x)‎</code> لأجل معامِلات <code>&amp;&amp;int</code>، بينما تجوز <code>(lamb1(x</code> لأن نوع <code>x</code> يُستنتج على أنه <code>&amp;int</code>. كذلك يمكن أن تكون دوالّ لامدا متغايرة (variadic)، وأن تعيد توجيه وسائطها:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_91" style="">
<span class="kwd">auto</span><span class="pln"> lam </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[](</span><span class="kwd">auto</span><span class="pun">&amp;&amp;...</span><span class="pln"> args</span><span class="pun">){</span><span class="kwd">return</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">args</span><span class="pun">)&gt;(</span><span class="pln">args</span><span class="pun">)...);};</span></pre>

<p>
	أو:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_93" style="">
<span class="kwd">auto</span><span class="pln"> lam </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[](</span><span class="kwd">auto</span><span class="pun">&amp;&amp;...</span><span class="pln"> args</span><span class="pun">){</span><span class="kwd">return</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">args</span><span class="pun">)(</span><span class="pln">args</span><span class="pun">)...);};</span></pre>

<p>
	والتي لن تعمل "بالشكل الصحيح" إلّا مع المتغيّرات من نوع <code>‎auto&amp;&amp;‎</code>. أيضًا، أحد الأسباب القوية لاستخدام دوال لامدا العامّة هو البنية اللغوية للزيارة (visiting syntax)، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_95" style="">
<span class="pln">boost</span><span class="pun">::</span><span class="pln">variant</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">double</span><span class="pun">&gt;</span><span class="pln"> value</span><span class="pun">;</span><span class="pln">
apply_visitor</span><span class="pun">(</span><span class="pln">value</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[&amp;](</span><span class="kwd">auto</span><span class="pun">&amp;&amp;</span><span class="pln"> e</span><span class="pun">){</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> e</span><span class="pun">;</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	هنا، قمنا هنا بالزيارة بأسلوب <a data-ss1617023045="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-16-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-%D8%A7%D9%84%D8%AA%D8%B9%D8%AF%D8%AF%D9%8A%D8%A9-%D8%A7%D9%84%D8%B4%D9%83%D9%84%D9%8A%D8%A9-polymorphism-%D9%81%D9%8A-cpp-r900/" rel="">متعدد الأشكال</a>، لكن في السياقات الأخرى فلا تهم أسماء النوع المُمرّرة:
</p>

<pre class="ipsCode">
mutex_wrapped&lt;std::ostream&amp;&gt; os = std::cout;
os.write([&amp;](auto&amp;&amp; os){
os &lt;&lt; "hello world\n";
});
</pre>

<p>
	لا فائدة من تكرار النوع <code>‎std::ostream&amp;‎</code> هنا؛ كأنك تذكر نوع المتغيّر في كل مرّة تستخدمه، ولقد أنشأنا هنا زائرًا غير متعدد الأشكال، كما استخدمنا <code>‎auto‎</code> هنا لنفس سبب استخدام <code>‎auto‎</code> في حلقة <code>‎for(:)‎</code>.
</p>

<h2>
	استخدام دوال لامدا لفك حزم المعاملات المضمنة
</h2>

<p>
	<strong>الإصدار ≥ C++‎ 14</strong>
</p>

<p>
	كان فكّ حزم المعامِلات (Parameter pack unpacking) يتطّلب كتابة دالّة مساعدة في كل مرّة تريد القيام بذلك. مثلًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_97" style="">
<span class="kwd">template</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pun">...</span><span class="typ">Is</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> print_indexes</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">index_sequence </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Is</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> discard </span><span class="pun">=</span><span class="pln"> </span><span class="typ">int</span><span class="pun">[];</span><span class="pln">
        </span><span class="pun">(</span><span class="kwd">void</span><span class="pun">)</span><span class="pln"> discard
        </span><span class="pun">{</span><span class="pln">
            </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="pun">((</span><span class="kwd">void</span><span class="pun">)(</span><span class="pln">
                std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="typ">Is</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln">    </span><span class="com">// هي ثابتة في وقت التصريف Is هنا</span><span class="pln">
        </span><span class="pun">),</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)...</span><span class="pln">
        </span><span class="pun">};</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> I</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> print_indexes_upto</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> print_indexes</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">make_index_sequence </span><span class="pun">&lt;</span><span class="pln"> I</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{});</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	يريد <code>‎print_indexes_upto‎</code> إنشاء وفكّ حزمة معاملات من الفهارس، ولفعل ذلك، يجب استدعاء دالّة مساعدة. يجب أن تنشئ دالة مساعدة مخصصة في كل مرة تريد فك حزمة معامِلات أنشأتها، ويمكن تجنب ذلك هنا باستخدام دوال لامدا، إذ يمكنك فكّ الحِزَم باستخدام دالة لامدا على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_99" style="">
<span class="kwd">template</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> I</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> </span><span class="typ">index_t</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">integral_constant</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pun">,</span><span class="pln"> I</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> I</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">constexpr</span><span class="pln"> </span><span class="typ">index_t</span><span class="pun">&lt;</span><span class="pln">I</span><span class="pun">&gt;</span><span class="pln"> index </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pun">...</span><span class="typ">Is</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> index_over</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">index_sequence </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Is</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pun">[](</span><span class="kwd">auto</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> f</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">using</span><span class="pln"> discard </span><span class="pun">=</span><span class="pln"> </span><span class="typ">int</span><span class="pun">[];</span><span class="pln">
            </span><span class="pun">(</span><span class="kwd">void</span><span class="pun">)</span><span class="pln"> discard
            </span><span class="pun">{</span><span class="pln">
                </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">void</span><span class="pun">(</span><span class="pln">
                    f</span><span class="pun">(</span><span class="pln">index </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Is</span><span class="pun">&gt;)</span><span class="pln">
            </span><span class="pun">),</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)...</span><span class="pln">
            </span><span class="pun">};</span><span class="pln">
        </span><span class="pun">};</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> N</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> index_over</span><span class="pun">(</span><span class="typ">index_t</span><span class="pun">&lt;</span><span class="pln">N</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{})</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> index_over</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">make_index_sequence </span><span class="pun">&lt;</span><span class="pln"> N</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{});</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 17</strong>
</p>

<p>
	يمكن تبسيط <code>‎index_over()‎</code> باستخدام التعبيرات المطوية على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_101" style="">
<span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pun">=</span><span class="kwd">void</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pun">...</span><span class="typ">Is</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> index_over</span><span class="pun">(</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">index_sequence</span><span class="pun">&lt;</span><span class="typ">Is</span><span class="pun">...&gt;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">[](</span><span class="kwd">auto</span><span class="pun">&amp;&amp;</span><span class="pln"> f</span><span class="pun">){</span><span class="pln">
</span><span class="pun">((</span><span class="kwd">void</span><span class="pun">)(</span><span class="pln">f</span><span class="pun">(</span><span class="pln">index</span><span class="pun">&lt;</span><span class="typ">Is</span><span class="pun">&gt;)),</span><span class="pln"> </span><span class="pun">...);</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	بعد ذلك، يمكنك استخدام هذا لتجنّب الحاجة إلى فكّ حزم المعاملات يدويًا عبر تحميل زائد ثانٍ في الشيفرات الأخرى، فذلك سيتيح لك فكّ حزم المعاملات بشكل مضمّن (inline):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_103" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Tup</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> F</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> for_each_tuple_element</span><span class="pun">(</span><span class="typ">Tup</span><span class="pun">&amp;&amp;</span><span class="pln"> tup</span><span class="pun">,</span><span class="pln"> F</span><span class="pun">&amp;&amp;</span><span class="pln"> f</span><span class="pun">)</span><span class="pln"> 
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> T </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">remove_reference_t</span><span class="pun">&lt;</span><span class="typ">Tup</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">tuple_size</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">auto</span><span class="pln"> from_zero_to_N </span><span class="pun">=</span><span class="pln"> index_over</span><span class="pun">&lt;</span><span class="pln">tuple_size </span><span class="pun">&lt;</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{}</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">();</span><span class="pln">
        from_zero_to_N</span><span class="pun">(</span><span class="pln">
        </span><span class="pun">[&amp;](</span><span class="kwd">auto</span><span class="pln"> i</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">get</span><span class="pun">;</span><span class="pln">
                f</span><span class="pun">(</span><span class="pln">get</span><span class="str">&lt;i&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="typ">Tup</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">tup</span><span class="pun">)));</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	نوع <code>‎auto i‎</code> المُمرّر إلى دالة لامدا عبر <code>‎index_over‎</code> هو <code>‎std::integral_constant&lt;std::size_t, ???&gt;‎</code> الذي يحتوي على تحويل <code>‎constexpr‎</code> إلى <code>std::size_t</code> لا يعتمد على حالة <code>this</code>، وعليه نستطيع استخدامه كثابت في وقت التصريف، مثلا عندما نمرّره إلى <code>‎std::get&lt;i&gt;‎</code> أعلاه.
</p>

<p>
	سنعيد الآن كتابة المثال أعلاه:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_105" style="">
<span class="kwd">template</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> I</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> print_indexes_upto</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        index_over</span><span class="pun">(</span><span class="pln">index </span><span class="pun">&lt;</span><span class="pln"> I</span><span class="pun">&gt;)([](</span><span class="kwd">auto</span><span class="pln"> i</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> i </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">    </span><span class="com">// هي ثابتة في وقت التصريف i هنا });</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	صار المثال أقصر بكثير. انظر إن شئت <a data-ss1617023045="1" href="coliru.stacked-crooked.com/a/32c204301f7163c9" rel="">هذا المثال الحيّ</a> على ذلك.
</p>

<h2>
	الالتقاطات المعممة النوع Generalized capture
</h2>

<p>
	<strong>الإصدار ≥ C++‎ 14</strong>
</p>

<p>
	تستطيع دوال لامدا التقاط التعبيرات وليس المتغيّرات فقط، هذا يسمح لدوال لامدا بتخزين أنواع النقل فقط (move-only types):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_107" style="">
<span class="kwd">auto</span><span class="pln"> p </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_unique</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(...);</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> lamb </span><span class="pun">=[</span><span class="pln">p </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">p</span><span class="pun">)]()</span><span class="pln">   
</span><span class="pun">{</span><span class="pln">
    p</span><span class="pun">-&gt;</span><span class="typ">SomeFunc</span><span class="pun">();</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	هذا ينقل المتغيّر <code>‎p‎</code> الخارجي إلى متغيّر لامدا المُلتقط ، ويسمى أيضًا <code>‎p‎</code>، وتمتلك <code>‎lamb‎</code> الآن الذاكرة المخصّصة لـ <code>‎make_unique‎</code>. وبما أن التغليف (closure) يحتوي على نوع غير قابل للنسخ، فذلك يعني أنّ <code>‎lamb‎</code> ستكون غير قابلة للنسخ، لكن ستكون قابلة للنقل رغم هذا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_109" style="">
<span class="kwd">auto</span><span class="pln"> lamb_copy </span><span class="pun">=</span><span class="pln"> lamb</span><span class="pun">;</span><span class="pln">    </span><span class="com">// غير جائز</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> lamb_move </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">lamb</span><span class="pun">);</span><span class="pln">    </span><span class="com">// جائز</span></pre>

<p>
	الآن أصبحت <code>‎lamb_move‎</code> تملك الذاكرة، لاحظ أنّ <code>‎std::function&lt;&gt;‎</code> تتطّلب أن تكون القيم المخزّنة قابلة للنسخ، يمكنك كتابة دالة خاصّة بك تتطّلب النقل فقط أو وضع لامدا في غلاف مؤشّر مشترك <code>‎shared_ptr‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_111" style="">
<span class="kwd">auto</span><span class="pln"> shared_lambda </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[](</span><span class="kwd">auto</span><span class="pun">&amp;&amp;</span><span class="pln"> f</span><span class="pun">){</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">[</span><span class="pln">spf </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_shared</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="typ">decay_t</span><span class="pun">&lt;</span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">f</span><span class="pun">)&gt;&gt;(</span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">f</span><span class="pun">)(</span><span class="pln">f</span><span class="pun">))]</span><span class="pln">
</span><span class="pun">(</span><span class="kwd">auto</span><span class="pun">&amp;&amp;...</span><span class="pln">args</span><span class="pun">)-&gt;</span><span class="kwd">decltype</span><span class="pun">(</span><span class="kwd">auto</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(*</span><span class="pln">spf</span><span class="pun">)(</span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">args</span><span class="pun">)(</span><span class="pln">args</span><span class="pun">)...);</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> lamb_shared </span><span class="pun">=</span><span class="pln"> shared_lambda</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">lamb_move</span><span class="pun">));</span></pre>

<p>
	هنا أخذنا دالة لامدا للنقل فقط ووضعنا حالتها في مؤشّر مشترك، ثم ستُعاد دالة لامدا قابلة للنسخ، ثم التخزين في <code>‎std::function‎</code> أو نحو ذلك.
</p>

<p>
	يستخدم الالتقاط المُعمّم استنباط النوع <code>‎auto‎</code> لاستنباط نوع المتغيّر، وسيصرّح عن هذه الالتقاطات على أنّها قيم افتراضيًا، لكن يمكن أن تكون مراجع أيضًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_113" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> lamb </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[&amp;</span><span class="pln">v </span><span class="pun">=</span><span class="pln"> a</span><span class="pun">](</span><span class="typ">int</span><span class="pln"> add</span><span class="pun">)</span><span class="pln">   </span><span class="com">// مختلفان `a` و `v` تذكّر أنّ اسمَي</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    v </span><span class="pun">+=</span><span class="pln"> add</span><span class="pun">;</span><span class="pln">    </span><span class="com">// `a` تعدي</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
lamb</span><span class="pun">(</span><span class="lit">20</span><span class="pun">);</span><span class="pln">    </span><span class="com">// ستصبح 20 `a` </span></pre>

<p>
	يستطيع الالتقاط المعمَّم أن يلتقط تعبيرًا عشوائيًا لكن لا يلزمه التقاط متغيرات خارجية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_115" style="">
<span class="kwd">auto</span><span class="pln"> lamb </span><span class="pun">=[</span><span class="pln">p </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_unique</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(...)]()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    p</span><span class="pun">-&gt;</span><span class="typ">SomeFunc</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هذا مفيد في إعطاء دوال لامدا قيمًا عشوائية يمكنها الاحتفاظ بها وربّما تعديلها دون الحاجة إلى التصريح عنها خارجيًا، بالطبع، هذا لا يكون مفيدًا إلّا إذا كنت تنوي الوصول إلى تلك المتغيّرات بعد أن تكمل لامدا عملها.
</p>

<h2>
	التحويل إلى مؤشر دالة
</h2>

<p>
	إذا كانت قائمة الالتقاط الخاصّة بلَامدا فارغة، فستُحوَّل لامدا ضمنيا إلى مؤشّر دالة يأخذ نفس الوسائط ويعيد نوع القيمة المُعادة نفسه:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_117" style="">
<span class="kwd">auto</span><span class="pln"> sorter </span><span class="pun">=[](</span><span class="typ">int</span><span class="pln"> lhs</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> rhs</span><span class="pun">)-&gt;</span><span class="kwd">bool</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> lhs </span><span class="pun">&lt;</span><span class="pln"> rhs</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> func_ptr </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">bool</span><span class="pun">(*)(</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">);</span><span class="pln">
func_ptr sorter_func </span><span class="pun">=</span><span class="pln"> sorter</span><span class="pun">;</span><span class="pln">    </span><span class="com">// تحويل ضمني</span></pre>

<p>
	يمكن أيضًا فرض هذا التحويل باستخدام عامل "+" الأحادي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_119" style="">
<span class="pln">func_ptr sorter_func2 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">+</span><span class="pln">sorter</span><span class="pun">;</span><span class="pln">    </span><span class="com">// فرض التحويل الضمني</span></pre>

<p>
	سيكون سلوك استدعاء مؤشّر الدالّة هذا مكافئًا لاستدعاء <code>‎operator()‎</code> على لامدا، فلا يعتمد مؤشّر الدالّة على وجود مغلّف لامدا، لذلك قد يستمرّ حتى بعد انتهاء مغلّف لامدا. هذه الميزة مفيدة عند استخدام دوال لامدا مع الواجهات البرمجية التي تتعامل مع مؤشّرات الدوال، بدلاً من كائنات دوال C++‎.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 14</strong>
</p>

<p>
	يمكن أيضًا تحويل دالة لامدا عامة لها قائمة التقاط فارغة إلى مؤشّر دالّة، وإذا لزم الأمر سيُستخدَم استنباط وسيط القالب (template argument deduction) لاختيار التخصيص الصحيح.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_121" style="">
<span class="kwd">auto</span><span class="pln"> sorter </span><span class="pun">=[](</span><span class="kwd">auto</span><span class="pln"> lhs</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> rhs</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> lhs </span><span class="pun">&lt;</span><span class="pln"> rhs</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> func_ptr </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">bool</span><span class="pun">(*)(</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">);</span><span class="pln">
func_ptr sorter_func </span><span class="pun">=</span><span class="pln"> sorter</span><span class="pun">;</span><span class="pln">    </span><span class="com">// int استنتاج</span><span class="pln">
</span><span class="com">// لكن السطر التالي غامض</span><span class="pln">
</span><span class="com">// func_ptr sorter_func2 = +sorter;</span></pre>

<h2>
	ترقية دوال لامدا إلى C++‎ 03 باستخدام الكائنات الدالية (functor)
</h2>

<p>
	دوال لامدا في C++‎ هي اختصارات مفيدة توفّر صياغة مختصرة لكتابة الدوال، ويمكن الحصول على وظيفة مشابهة في C++‎ 03 (وإن كانت مُطولًة) عن طريق تحويل دالّة لامدا إلى كائن دالّي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_123" style="">
<span class="com">// هذه بعض الأنواع</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> T1
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> dummy</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> T2
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> dummy</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> R
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> dummy</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	هذه الشيفرة تستخدم دالة لامدا،هذا يعني أنها تستلزم C++11، نتابع المثال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_127" style="">
<span class="pln">R use_lambda</span><span class="pun">(</span><span class="pln">T1 val</span><span class="pun">,</span><span class="pln"> T2 ref</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span></pre>

<p>
	هنا، استعمل <code>auto</code> لأن النوع المُعاد من دالة لامدا مجهول، نتابع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_129" style="">
<span class="pln">    </span><span class="kwd">auto</span><span class="pln"> lambda </span><span class="pun">=[</span><span class="pln">val</span><span class="pun">,</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">ref</span><span class="pun">](</span><span class="typ">int</span><span class="pln"> arg1</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> arg2</span><span class="pun">)-&gt;</span><span class="pln">R
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">/* متن لامدا */</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> R</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> lambda</span><span class="pun">(</span><span class="lit">12</span><span class="pun">,</span><span class="pln"> </span><span class="lit">27</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// C++03 صنف الكائن الدالي - صالح في</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Functor</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// قائمة الالتقاط</span><span class="pln">
    T1 val</span><span class="pun">;</span><span class="pln">
    T2 </span><span class="pun">&amp;</span><span class="pln">ref</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="com">// المنشئ</span><span class="pln">
        </span><span class="kwd">inline</span><span class="pln"> </span><span class="typ">Functor</span><span class="pun">(</span><span class="pln">T1 val</span><span class="pun">,</span><span class="pln"> T2 </span><span class="pun">&amp;</span><span class="pln">ref</span><span class="pun">):</span><span class="pln"> val</span><span class="pun">(</span><span class="pln">val</span><span class="pun">),</span><span class="pln"> ref</span><span class="pun">(</span><span class="pln">ref</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

    </span><span class="com">// متن الكائن الدالي</span><span class="pln">
    R </span><span class="kwd">operator</span><span class="pun">()(</span><span class="typ">int</span><span class="pln"> arg1</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> arg2</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">/* متن لامدا */</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> R</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	هذا يكافئ <code>use_lambda</code> لكنه يستخدم كائنًا دالّيًا، وهو صالح في C++03:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_131" style="">
<span class="pln">R use_functor</span><span class="pun">(</span><span class="pln">T1 val</span><span class="pun">,</span><span class="pln"> T2 ref</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Functor</span><span class="pln"> functor</span><span class="pun">(</span><span class="pln">val</span><span class="pun">,</span><span class="pln"> ref</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> functor</span><span class="pun">(</span><span class="lit">12</span><span class="pun">,</span><span class="pln"> </span><span class="lit">27</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    T1 t1</span><span class="pun">;</span><span class="pln">
    T2 t2</span><span class="pun">;</span><span class="pln">
    use_functor</span><span class="pun">(</span><span class="pln">t1</span><span class="pun">,</span><span class="pln"> t2</span><span class="pun">);</span><span class="pln">
    use_lambda</span><span class="pun">(</span><span class="pln">t1</span><span class="pun">,</span><span class="pln"> t2</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	إذا كانت دالّة لامدا قابلة للتغيير (<code>‎mutable‎</code>)، فاجعل مُعامل الاستدعاء الخاص بالكائن الدالّي غير ثابت، أي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6627_133" style="">
<span class="pln">R </span><span class="kwd">operator</span><span class="pun">()(</span><span class="typ">int</span><span class="pln"> arg1</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> arg2</span><span class="pun">)</span><span class="pln"> </span><span class="com">/*non-const*/</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">/* متن لامدا */</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> R</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617023045="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 73: Lambdas من كتاب <a data-ss1617023045="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">960</guid><pubDate>Wed, 26 Aug 2020 18:06:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x627;&#x633;&#x62A;&#x62B;&#x646;&#x627;&#x621;&#x627;&#x62A; Exceptions &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%AB%D9%86%D8%A7%D8%A1%D8%A7%D8%AA-exceptions-%D9%81%D9%8A-cpp-r959/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_08/38.png.fc3263b10006db97e44c1f4781d34ac8.png" /></p>

<h2>
	إمساك الاستثناءات Catching exceptions
</h2>

<p>
	تُستخدَم الكتلة <code>‎try/catch‎</code> لإمساك الاستثناءات إذ توضع في القسم <code>‎try‎</code> الشيفراتُ التي يُشتبه في أنّها قد ترفع استثناءً، فيما تتكفّل الشيفرة الموضوعة في الكتلة <code>‎catch‎</code> بمعالجة الاستثناء حال رفعه.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8219_7" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;string&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;stdexcept&gt;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">string str</span><span class="pun">(</span><span class="str">"foo"</span><span class="pun">);</span><span class="pln">

    </span><span class="kwd">try</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        str</span><span class="pun">.</span><span class="pln">at</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln">    </span><span class="com">// std::out_of_range محاولة الدخول إلى العنصر قد تؤدي إلى رفع</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">out_of_range </span><span class="pun">&amp;</span><span class="pln">e</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// وتحتوي رسالة توضيحية std::exception موروثة من  what() </span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">what</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكن استخدام عدة كتل <code>‎catch‎</code> للتعامل مع أكثر من نوع ٍمن الاستثناءات، وفي حال استخدام عدة عبارات <code>‎catch‎</code> فإنّّ آلية معالجة الاستثناءات ستحاول مطابقتها بحسب ترتيب ظهورها في الشيفرة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8219_9" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">string str</span><span class="pun">(</span><span class="str">"foo"</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">try</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    str</span><span class="pun">.</span><span class="pln">reserve</span><span class="pun">(</span><span class="lit">2</span><span class="pun">);</span><span class="pln">    </span><span class="com">// std::length_error محاولة تخصيص سعة زائدة قد تؤدي إلى رفع</span><span class="pln">
    str</span><span class="pun">.</span><span class="pln">at</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln">    </span><span class="com">// std::out_of_range محاولة الدخول إلى هذا العنصر سترفع</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">length_error </span><span class="pun">&amp;</span><span class="pln">e</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">what</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">out_of_range </span><span class="pun">&amp;</span><span class="pln">e</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">what</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكن إمساك أصناف الاستثناءات المشتقّة من صنف أساسي باستخدام عبارة <code>‎catch‎</code> واحدة مخصّصة للصنف الأساسي. ويمكن استبدال العبارتين <code>‎catch‎</code> الخاصتين بالاستثنائَين <code>‎std::length_error‎</code> و <code>std::out_of_range</code> في المثال أعلاه بعبارة <code>‎catch‎</code> واحدة موجّهة للاستثناء <code>std:exception</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8219_11" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">string str</span><span class="pun">(</span><span class="str">"foo"</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">try</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    str</span><span class="pun">.</span><span class="pln">reserve</span><span class="pun">(</span><span class="lit">2</span><span class="pun">);</span><span class="pln">    </span><span class="com">// std::length_error محاولة تخصيص سِعة زائدة قد تؤدي إلى رفع</span><span class="pln">
    str</span><span class="pun">.</span><span class="pln">at</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln">    </span><span class="com">// std::out_of_range محاولة الدخول إلى هذا العنصر سترفع</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">exception </span><span class="pun">&amp;</span><span class="pln">e</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">what</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ونظرًا لأنّ عبارات <code>‎catch‎</code> تُختبَر بالترتيب، فتأكد من كتابة عبارات <code>catch</code> الأكثر تخصيصًا أولاً، وإلا فقد لا تُستدعى شيفرة الاستثناء المخصوصة أبدًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9874_7" style="">
<span class="kwd">try</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">/* شيفرة ترفع استثناء */</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">exception </span><span class="pun">&amp;</span><span class="pln">e</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">/* std::exception معالجة كل الاستثناءات من النوع */</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">runtime_error </span><span class="pun">&amp;</span><span class="pln">e</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لن تُنفَّذ الكتلة الأخيرة في الشيفرة السابقة لأن <code>std::runtime_error</code> ترث من <code>std::exception</code>، وقد أُمسكت كل استثناءات <code>std::exception</code> من قِبل تعليمة <code>catch</code> التي سبقتها. هناك حلّ آخر، وهو استخدام عبارة <code>catch</code> تعالج كل الاستثناءات، على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8219_15" style="">
<span class="kwd">try</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">throw</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(...)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"caught an exception"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	إعادة رفع استثناء
</h2>

<p>
	قد ترغب أحيانًا أن تفعل شيئًا بالاستثناء الذي أمسكته، مثل كتابته في سجل الأخطاء، أو طباعة تحذير، ثمّ إعادة رفعه إلى النطاق الأعلى لكي يُعالج هناك. وهذا ممكن، إذ يمكنك إعادة رفع أيّ استثناء تمسكه، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8219_17" style="">
<span class="kwd">try</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="pun">...</span><span class="pln">    </span><span class="com">// شيفرة هنا</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">SomeException</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">e</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"caught an exception"</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">throw</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يؤدّي استخدام <code>‎throw;‎</code> بدون وسائط إلى إعادة رفع الاستثناء الممسوك حاليًا.
</p>

<h3>
	<strong>الإصدار ≥ C++‎ 11</strong>
</h3>

<p>
	لإعادة رفع استثناء <code>std::exception_ptr‎</code> سبقت إدارته، توفّر مكتبة C++‎ القياسية دالّة <code>‎rethrow_exception‎</code> يمكن استخدامها عبر تضمين ترويسة <exception> في البرنامج. </exception></p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9874_9" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;string&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;exception&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;stdexcept&gt;</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> handle_eptr</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">exception_ptr eptr</span><span class="pun">)</span><span class="pln">    </span><span class="com">// لا حرج في التمرير بالقيمة</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">try</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">eptr</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">rethrow_exception</span><span class="pun">(</span><span class="pln">eptr</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">exception </span><span class="pun">&amp;</span><span class="pln">e</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Caught exception \""</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">what</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\"\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">exception_ptr eptr</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">try</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">().</span><span class="pln">at</span><span class="pun">(</span><span class="lit">1</span><span class="pun">);</span><span class="pln">    </span><span class="com">// std::out_of_range ًسيولّد هذا استثناء</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(...)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        eptr </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">current_exception</span><span class="pun">();</span><span class="pln">    </span><span class="com">// إمساك</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    handle_eptr</span><span class="pun">(</span><span class="pln">eptr</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">    </span><span class="com">// eptr هنا عند تدمير std::out_of_range سيُستدعى مدمّر</span></pre>

<h2>
	أفضل تطبيق: رفع الاستثناءات بالقيمة وإمساكها بالمراجع الثابتة
</h2>

<p>
	بشكل عام، يُوصى برفع الاستثناء بالقيمة (بدلاً من رفعه بالمؤشّر)، ولكن يوصى بإمساكه بالمراجع الثابتة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9874_11" style="">
<span class="kwd">try</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// throw new std::runtime_error("Error!");        // لا تفعل هذا</span><span class="pln">
    </span><span class="com">// سينشئ هذا كائن استثناء في الكومة، وسيتطلّب منك أن تمسك المؤشر وتدير الذاكرة بنفسك</span><span class="pln">
    </span><span class="com">// وهذا قد يُسبِّب تسرّب الذاكرة</span><span class="pln">

    </span><span class="kwd">throw</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">runtime_error</span><span class="pun">(</span><span class="str">"Error!"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">runtime_error </span><span class="pun">&amp;</span><span class="pln">e</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">what</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	أحد الأسباب التي تجعل الإمساك بالمرجع أفضل، هو أنّه يلغي الحاجة إلى إعادة بناء الكائن عند نقله إلى كتلة <code>catch</code> (أو عند نشره إلى كتل <code>catch</code> الأخرى)، كما يتيح الإمساك بالمرجع معالجة الاستثناءات بأسلوب تعدد الأشكال، ويتجنّب تشريح slicing الكائنات، لكن إن كنت تريد إعادة رفع استثناء مثل <code>‎throw e;‎</code>، انظر المثال أدناه، فلا يزال بإمكانك تشريح الكائن لأنّ تعليمة <code>‎throw e;‎</code> تنشئ نسخة من الاستثناء من النّوع المُصرّح عنه:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8219_23" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">BaseException</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">*</span><span class="pln">what</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="str">"BaseException"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">DerivedException</span><span class="pun">:</span><span class="pln"> </span><span class="typ">BaseException</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// اختيارية هنا "virtual" الكلمة المفتاحية</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">*</span><span class="pln">what</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="str">"DerivedException"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> argc</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">**</span><span class="pln">argv</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">try</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">try</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">throw</span><span class="pln"> </span><span class="typ">DerivedException</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">BaseException</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">e</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"First catch block: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">what</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
            </span><span class="com">// ==&gt; First catch block: DerivedException</span><span class="pln">
            </span><span class="kwd">throw</span><span class="pln"> e</span><span class="pun">;</span></pre>

<p>
	سيغير ذلك الاستثناء من <code>DerivedException</code> إلى <code>BaseException</code>، تابع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8219_25" style="">
<span class="pln">        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">BaseException</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">e</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Second catch block: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">what</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
        </span><span class="com">// ==&gt; Second catch block: BaseException</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	إذا كنت متأكدًا من أنك لن تفعل أيّ شيء يؤدي إلى تغيير الاستثناء (مثل إضافة معلومات أو تعديل رسالة الخطأ المرفقة بالاستثناء)، فإنّّ إمساك الاستثناء بمرجع ثابت سيسمح للمٌصرّف بإجراء بعض التحسينات، ولكن هذا لن يلغي بالضرورة الحاجة إلى تشريح الكائن (كما هو مُوضّح في المثال أعلاه).
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<div class="ipsQuote_contents ipsClearfix">
		<p>
			<strong>تحذير</strong>: احذر من رفع استثناءات غير مقصودة في كتلة <code>‎catch‎</code>، خاصّة تلك المتعلّقة منها بتخصيص ذاكرةٍ أو موارد إضافية، فمثلًا قد يؤدّي إنشاء <code>‎logic_error‎</code> أو <code>‎runtime_error‎</code> أو الأصناف الفرعية المشتقّة منهما إلى رفع <code>‎bad_alloc‎</code> نتيجة نفاد الذاكرة عند نسخ السلسلة النصّية الخاصة بالاستثناء، وقد ترفع مجاري الدخل/الخرج استثناءً أثناء تسجيل الأخطاء logging باستخدام أقنعة الاستثناءات exception masks المرتبطة بها.
		</p>
	</div>
</blockquote>

<h2>
	الاستثناءات المخصصة
</h2>

<p>
	ينبغي ألّا ترفع قيمًا خامًا raw values مثل استثناءات، بل استخدم أحد أصناف الاستثناءات القياسية أو اصنع واحدًا خاصًّا بك، ويُعدّ إنشاء صنف استثناء موروث من <code>‎std::exception‎</code> أسلوبًا مستحسنًا. في المثال التالي، انظر صنف استثناء مخصّص يرث مباشرةً من <code>‎std::exception‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8219_27" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;exception&gt;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Except</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">exception
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pun">:</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> error_number</span><span class="pun">;</span><span class="pln">    </span><span class="com">///&lt; Error number</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> error_offset</span><span class="pun">;</span><span class="pln">    </span><span class="com">///&lt; Error offset</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">string error_message</span><span class="pun">;</span><span class="pln">    </span><span class="com">///&lt; Error message</span><span class="pln">

    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="com">/**Constructor (C++ STL string, int, int).
         * @param msg The error message
         * @param err_num Error number
         * @param err_off Error offset
         */</span><span class="pln">
        </span><span class="kwd">explicit</span><span class="pln">
    </span><span class="typ">Except</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&amp;</span><span class="pln">msg</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> err_num</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> err_off</span><span class="pun">):</span><span class="pln"> error_number</span><span class="pun">(</span><span class="pln">err_num</span><span class="pun">),</span><span class="pln">
    error_offset</span><span class="pun">(</span><span class="pln">err_off</span><span class="pun">),</span><span class="pln">
    error_message</span><span class="pun">(</span><span class="pln">msg</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span></pre>

<p>
	المدمر: يكون وهميًا Virtual من أجل السماح بالتصنيف الفرعي، تابع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8219_29" style="">
<span class="pln">    </span><span class="kwd">virtual</span><span class="pun">~</span><span class="typ">Except</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">throw</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span></pre>

<p>
	نعيد مؤشرًا يشير إلى وصف الخطأ الثابت، ومؤشرًا يشير إلى <code>*const char</code>، وتحتوي الذاكرة الأساسية على الكائن <code>Except</code>، ويجب ألا يحاول المستدعون أن يحرروا الذاكرة. انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8219_31" style="">
<span class="pln">    </span><span class="kwd">virtual</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">*</span><span class="pln">what</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
    </span><span class="kwd">throw</span><span class="pln"> </span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> error_message</span><span class="pun">.</span><span class="pln">c_str</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">/**Returns error number.
     * @return #error_number
     */</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> getErrorNumber</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
    </span><span class="kwd">throw</span><span class="pln"> </span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> error_number</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">/**Returns error offset.
     *@return #error_offset
     */</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> getErrorOffset</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
    </span><span class="kwd">throw</span><span class="pln"> </span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> error_offset</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	هذا مثال تطبيقي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8219_33" style="">
<span class="kwd">try</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">throw</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Except</span><span class="pun">(</span><span class="str">"Couldn't do what you were expecting"</span><span class="pun">,</span><span class="pln"> </span><span class="pun">-</span><span class="lit">12</span><span class="pun">,</span><span class="pln"> </span><span class="pun">-</span><span class="lit">34</span><span class="pun">));</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Except</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">e</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">what</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln">
        </span><span class="str">"\nError number: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">getErrorNumber</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln">
        </span><span class="str">"\nError offset: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">getErrorOffset</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	بهذه الطريقة فإنّك لا ترفع رسالة خطأ وحسب، ولكن ترفع أيضًا بعض القيم الأخرى التي توضّح طبيعة الخطأ بالضبط، وهكذا يصبح التعامل مع الأخطاء أسهل وأيسر. يوجد صنف استثناء يتيح لك معالجة رسائل الخطأ بسهولة، وهو <code>‎std::runtime_error‎</code>، تستطيع الاشتقاق من هذا الصنف على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8219_35" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;stdexcept&gt;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Except</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">runtime_error
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pun">:</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> error_number</span><span class="pun">;</span><span class="pln">    </span><span class="com">///&lt; Error number</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> error_offset</span><span class="pun">;</span><span class="pln">    </span><span class="com">///&lt; Error offset</span><span class="pln">

    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="com">/**Constructor (C++ STL string, int, int).
         * @param msg The error message
         * @param err_num Error number
         * @param err_off Error offset
         */</span><span class="pln">
        </span><span class="kwd">explicit</span><span class="pln">
    </span><span class="typ">Except</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&amp;</span><span class="pln">msg</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> err_num</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> err_off</span><span class="pun">):</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">runtime_error</span><span class="pun">(</span><span class="pln">msg</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        error_number </span><span class="pun">=</span><span class="pln"> err_num</span><span class="pun">;</span><span class="pln">
        error_offset </span><span class="pun">=</span><span class="pln"> err_off</span><span class="pun">;</span><span class="pln">

    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">/** المدمر
     * للسماح بالاشتقاق Virtual الكلمة المفتاحية
     */</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pun">~</span><span class="typ">Except</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">throw</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

    </span><span class="com">/**Returns error number.
     * @return #error_number
     */</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> getErrorNumber</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
    </span><span class="kwd">throw</span><span class="pln"> </span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> error_number</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">/**Returns error offset.
     *@return #error_offset
     */</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> getErrorOffset</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
    </span><span class="kwd">throw</span><span class="pln"> </span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> error_offset</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	لاحظ أنّك لم تُعِدْ تعريف الدالّة <code>‎what()‎</code> من الصنف الأساسي (<code>‎std::runtime_error‎</code>)، أي أنّنا سنستخدم إصدار الصنف الأساسي من <code>‎what()‎</code>، لكن لا شيء يمنعك من إعادة تعريفها إن أردت.
</p>

<h2>
	std::uncaught_exceptions
</h2>

<p>
	<strong>الإصدار ≥ C++‎ 17</strong>
</p>

<p>
	تقدّم C++‎ 17 النوع <code>‎int std::uncaught_exceptions()‎</code> (ليحلّ محلّ النوع <code>‎bool std::uncaught_exception()‎</code> المحدود) لمعرّفة عدد الاستثناءات غير الممسوكة حاليًا، يتيح هذا للأصناف معرفة ما إذا كان الاستثناء قد دُمِّر أثناء فكّ المكدّس stack unwinding أم لا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9874_15" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;exception&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;string&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

   </span><span class="com">// تطبيق التغيير عند التدمير:</span><span class="pln">
   </span><span class="com">// في حال رفع استثناء: Rollback.</span><span class="pln">
   </span><span class="com">// غير ذلك: Commit.</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Transaction</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Transaction</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&amp;</span><span class="pln">s</span><span class="pun">):</span><span class="pln"> message</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

    </span><span class="typ">Transaction</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Transaction</span><span class="pln"> </span><span class="pun">&amp;)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">delete</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">Transaction</span><span class="pln"> </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pun">=(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Transaction</span><span class="pln"> </span><span class="pun">&amp;)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">delete</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Commit</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> message </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">": Commit\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">RollBack</span><span class="pun">()</span><span class="pln"> noexcept</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> message </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">": Rollback\n"</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="com">// ...</span><span class="pln">
        </span><span class="pun">~</span><span class="typ">Transaction</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">uncaughtExceptionCount </span><span class="pun">==</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">uncaught_exceptions</span><span class="pun">())</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="typ">Commit</span><span class="pun">();</span><span class="pln">    </span><span class="com">// قد يُطرَح استثناء</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
            </span><span class="kwd">else</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="com">// فك المكدّس الحالي</span><span class="pln">
                </span><span class="typ">RollBack</span><span class="pun">();</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">string message</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> uncaughtExceptionCount </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">uncaught_exceptions</span><span class="pun">();</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="pun">~</span><span class="typ">Foo</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">try</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="typ">Transaction</span><span class="pln"> transaction</span><span class="pun">(</span><span class="str">"In ~Foo"</span><span class="pun">);</span><span class="pln"> </span><span class="com">// حتى لو كان هناك استثناء غير ممسوك commit الاعتماد  </span><span class="pln">
                </span><span class="com">//...</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">

            </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">exception </span><span class="pun">&amp;</span><span class="pln">e</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                std</span><span class="pun">::</span><span class="pln">cerr </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"exception/~Foo:"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">what</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">try</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Transaction</span><span class="pln"> transaction</span><span class="pun">(</span><span class="str">"In main"</span><span class="pun">);</span><span class="pln">    </span><span class="com">// RollBack (تراجع)</span><span class="pln">
        </span><span class="typ">Foo</span><span class="pln"> foo</span><span class="pun">;</span><span class="pln">    </span><span class="com">//  يعتمد المعاملة ~Foo</span><span class="pln">
        </span><span class="com">//...</span><span class="pln">
        </span><span class="kwd">throw</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">runtime_error</span><span class="pun">(</span><span class="str">"Error"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">exception </span><span class="pun">&amp;</span><span class="pln">e</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cerr </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"exception/main:"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">what</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الناتج:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8219_39" style="">
<span class="typ">In</span><span class="pun">~</span><span class="typ">Foo</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Commit</span><span class="pln">
</span><span class="typ">In</span><span class="pln"> main</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Rollback</span><span class="pln">
exception </span><span class="pun">/</span><span class="pln"> main</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Error</span></pre>

<h2>
	استخدام كتلة <code>try</code> في الدوال العادية
</h2>

<p>
	إليك المثال التوضيحي التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8219_41" style="">
<span class="kwd">void</span><span class="pln"> function_with_try_block</span><span class="pun">()</span><span class="pln">
</span><span class="kwd">try</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// شيفرة هنا</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(...)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// شيفرة هنا</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	والذي يكافئ:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8219_43" style="">
<span class="kwd">void</span><span class="pln"> function_with_try_block</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">try</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// شيفرة هنا</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(...)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">//  شيفرة هنا</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لاحظ أنّه بالنسبة للمنشئات والمدمّرات فإنّّ السلوك يكون مختلفًا لأنّ كتلة <code>catch</code> تعيد رفع استثناء على أيّ حال (الاستثناء الممسوك في حال لم يكن هناك رفع الاستثناء آخر في جسم كتلة <code>catch</code>).
</p>

<p>
	ويُسمح للدّالّة <code>‎main‎</code> أن تحتوي على كتلة <code>try</code> مثل أيّ دالّة أخرى، بيْد أنّ كتلة <code>try</code> في الدالة <code>‎main‎</code> لن تمسك الاستثناءات التي تحدث أثناء إنشاء المتغيّرات الساكنة غير المحلية، أو عند تدمير أيّ متغيّر ساكن، لكن بدلاً من ذلك تُستدعى <code>‎std::terminate‎</code>.
</p>

<h2>
	الاستثناء المتداخل
</h2>

<h3>
	<strong>الإصدار ≥ C++‎ 11</strong>
</h3>

<p>
	أثناء معالجة الاستثناء، يمكن إمساك استثناء عام من دالّة ذات مستوى منخفض (مثل خطأ في نظام الملفّات أو خطأ في نقل البيانات) ورفع استثناء عالي المستوى أكثر تخصيصًا يشير إلى أنّه قد تعذّر تقديم بعض العمليات عالية المستوى (مثل عدم القدرة على نشر صورة على الويب).
</p>

<p>
	يسمح ذلك بالاستجابة للمشاكل الخاصّة بالعمليات عالية المستوى، كما يسمح للمبرمج بإيجاد مكان وقوع الاستثناء في التطبيق، الجانب السلبي في هذا الحل هو أنّ مكدّس الاستدعاءات callstack الخاص بالاستثناء سيُقتطَع، وسيُفقد الاستثناء الأصلي، ويفرض هذا على المطوّرين تضمين نصّ الاستثناء الأصلي يدويًا في آخر استثناء مُنشأ.
</p>

<p>
	تهدف الاستثناء المتداخلة <code>std::nested_exception</code> إلى حل هذه المشكلة عن طريق إرفاق استثناء منخفض المستوى، والذي يصف سبب رفع الاستثناء، باستثناء عالي المستوى، والذي يصف ما يعنيه الاستثناء في هذه الحالة بالذات.
</p>

<p>
	يسمح الاستثناء المتداخل بتداخل الاستثناءات بفضل <code>std::throw_with_nested</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9874_17" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;stdexcept&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;exception&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;string&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;fstream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">MyException</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">MyException</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&amp;</span><span class="pln">message</span><span class="pun">):</span><span class="pln"> message</span><span class="pun">(</span><span class="pln">message</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

    std</span><span class="pun">::</span><span class="pln">string message</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> print_current_exception</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> level</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">try</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">throw</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">exception </span><span class="pun">&amp;</span><span class="pln">e</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cerr </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">(</span><span class="pln">level</span><span class="pun">,</span><span class="pln"> </span><span class="str">' '</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"exception: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">what</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">MyException</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">e</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cerr </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">(</span><span class="pln">level</span><span class="pun">,</span><span class="pln"> </span><span class="str">' '</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"MyException: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">message </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(...)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cerr </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Unkown exception\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> print_current_exception_with_nested</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> level </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">try</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">throw</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(...)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        print_current_exception</span><span class="pun">(</span><span class="pln">level</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">try</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">throw</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">nested_exception </span><span class="pun">&amp;</span><span class="pln">nested</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">try</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            nested</span><span class="pun">.</span><span class="pln">rethrow_nested</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(...)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            print_current_exception_with_nested</span><span class="pun">(</span><span class="pln">level </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">    </span><span class="com">// (Recursion) ذاتية</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(...)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">//فارغ    // (Recursion) إنهاء الذاتية</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// دالة بسيطة تمسك استثناء وتغلّفه في استثناء متداخل</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> open_file</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&amp;</span><span class="pln">s</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">try</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">ifstream file</span><span class="pun">(</span><span class="pln">s</span><span class="pun">);</span><span class="pln">
        file</span><span class="pun">.</span><span class="pln">exceptions</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ios_base</span><span class="pun">::</span><span class="pln">failbit</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(...)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">throw_with_nested</span><span class="pun">(</span><span class="typ">MyException</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="str">"Couldn't open "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> s </span><span class="pun">});</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// دالة بسيطة تمسك استثناء وتغلّفه في اسستثناء متداخل</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> run</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">try</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        open_file</span><span class="pun">(</span><span class="str">"nonexistent.file"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(...)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">throw_with_nested</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">runtime_error</span><span class="pun">(</span><span class="str">"run() failed"</span><span class="pun">));</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// تشغيل الدالة أعلاه وطباعة الاستثناء الممسوك</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">try</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        run</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(...)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        print_current_exception_with_nested</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الخرج المحتمل:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8219_47" style="">
<span class="pln">exception</span><span class="pun">:</span><span class="pln"> run</span><span class="pun">()</span><span class="pln"> failed
</span><span class="typ">MyException</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Couldn</span><span class="pln"> </span><span class="str">'</span><span class="pln">t open nonexistent</span><span class="pun">.</span><span class="pln">file
exception</span><span class="pun">:</span><span class="pln"> basic_ios</span><span class="pun">::</span><span class="pln">clear</span></pre>

<p>
	إذا كنت تعمل حصرًا مع الاستثناءات الموروثة من <code>‎std::exception‎</code>، فهناك إمكانية لتبسيط الشيفرة أكثر.
</p>

<h2>
	استخدام كتلة Try في المنشئات
</h2>

<p>
	الطريقة التالية هي الوحيدة لإمساك استثناء في قائمة مهيئ:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8219_49" style="">
<span class="kwd">struct</span><span class="pln"> A</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> B
</span><span class="pun">{</span><span class="pln">
    A</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">try</span><span class="pun">:</span><span class="pln"> B</span><span class="pun">(),</span><span class="pln"> foo</span><span class="pun">(</span><span class="lit">1</span><span class="pun">),</span><span class="pln"> bar</span><span class="pun">(</span><span class="lit">2</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// جسم المنشئ</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(...)</span><span class="pln">
    </span><span class="pun">{</span></pre>

<p>
	تُمسَك الاستثناءات الناجمة عن قائمة المهيئ والمنشئ هنا، وسيعاد رفع الاستثناء الممسوك عند عدم رفع أي استثناء، نتابع المثال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8219_51" style="">
<span class="pln">    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Foo</span><span class="pln"> foo</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">Bar</span><span class="pln"> bar</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<h2>
	استخدام كتلة Try في المدمرات
</h2>

<p>
	انظر المثال التوضيحي التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9874_23" style="">
<span class="kwd">struct</span><span class="pln"> A
</span><span class="pun">{</span><span class="pln">
    </span><span class="pun">~</span><span class="pln">A</span><span class="pun">()</span><span class="pln"> noexcept</span><span class="pun">(</span><span class="kwd">false</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">try</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// جسم المدمّر</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(...)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// الاستثناءات الناجمة عن جسم المدمّر تُمسَك هنا</span><span class="pln">
        </span><span class="com">// في حال عدم رفع أيّ استثناء هنا، فسيُعاد رفع الاستثناء الممسوك</span><span class="pln">

    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	رغم أنّه يمكن رفع استثناء من المدمّر، إلّا أنّه ينبغي التزام الحذر، ذلك أنّه في حال رفع استثناء في مدمّر مُستدعًى أثناء فكّ المكدّس، فإنّّ ذلك سيتسبّب في استدعاء <code>‎std::terminate‎</code>.
</p>

<p>
	هذا الدرس جزء من <a data-ss1617023046="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 72: Exceptions من كتاب <a data-ss1617023046="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">959</guid><pubDate>Mon, 24 Aug 2020 18:01:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x633;&#x644;&#x648;&#x643; &#x627;&#x644;&#x645;&#x62A;&#x639;&#x644;&#x642; &#x628;&#x627;&#x644;&#x62A;&#x646;&#x641;&#x64A;&#x630; Implementation-defined behavior &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%B3%D9%84%D9%88%D9%83-%D8%A7%D9%84%D9%85%D8%AA%D8%B9%D9%84%D9%82-%D8%A8%D8%A7%D9%84%D8%AA%D9%86%D9%81%D9%8A%D8%B0-implementation-defined-behavior-%D9%81%D9%8A-cpp-r958/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_08/37.png.dcc15d0376adc914aa98d26bb46e97cd.png" /></p>

<h2>
	حجم الأنواع العددية الصحيحة
</h2>

<p>
	الأنواع التالية هي أنواع عددية صحيحة:
</p>

<ul>
<li>
		<code>‎char‎</code>
	</li>
	<li>
		الأنواع العددية الصحيحة المُؤشّرة Signed integer types
	</li>
	<li>
		الأنواع العددية الصحيحة غير المُؤشّرة Unsigned integer types
	</li>
	<li>
		<code>‎char16_t‎</code> و <code>‎char32_t‎</code>
	</li>
	<li>
		<code>‎bool‎</code>
	</li>
	<li>
		<code>‎wchar_t‎</code>
	</li>
</ul>
<p>
	باستثناء <code>‎sizeof(char)‎</code> و <code>‎sizeof(signed char)‎</code> و <code>‎sizeof(unsigned char)‎</code>، الموجودة بين الفقرة ‎‎ 3.9.1.1 [basic.fundamental/1] ‎‎ و‎‎الفقرة 5.3.3.1 ‎‎[expr.sizeof]‎‎ و <code>‎sizeof(bool)‎</code>، والتي تتوقف على التنفيذ بالكامل وليس لها حدّ أدنى، فإنّّ متطلّبات الحد الأدنى لأحجام هذه الأنواع موجود في القسم 3.9.1 ‏‎[basic.fundamental]‎‎ من المعيار، وسنوضّحه أدناه.
</p>

<h3>
	حجم char
</h3>

<p>
	تحدّد جميع إصدارات معيار C++‎، في الفقرة 5.3.3.1، أنّ <code>‎sizeof‎</code> تعيد القيمة <code>‎1‎</code> لكلّ من <code>‎unsigned char‎</code> و <code>‎signed char‎</code> و <code>‎char‎</code> (مسألة ما إذا كان النوع <code>‎char‎</code> مؤشّرا - <code>‎signed‎</code> - أو غير مؤشّر - <code>‎unsigned‎</code> - تتعلّق بالتنفيذ).
</p>

<p>
	<strong>الإصدار ≥ C++‎ 14</strong>
</p>

<p>
	النوع <code>‎char‎</code> كبير بما يكفي لتمثيل 256 قيمة مختلفة، وهو مناسب لتخزين وحدات رموز UTF-8.
</p>

<h3>
	حجم الأنواع العددية الصحيحة المُؤشّرة وغير المُؤشّرة
</h3>

<p>
	تنصّ المواصفات القياسية، في الفقرة 3.9.1.2، أنّه في قائمة أنواع الأعداد الصحيحة القياسية المُؤشّرة، التي تتكون من <code>‎signed char‎</code> و <code>‎short ‎int‎</code> و <code>‎int‎</code> و <code>‎long ‎int‎</code> و <code>‎long ‎long ‎int‎</code>، فإنّّ كل نوع سيوفّر مساحة تخزينية تكافئ على الأقل المساحة التخزينيّة للنّوع السابق في القائمة. إضافة لذلك، وكما هو مُوضّح في الفقرة 3.9.1.3، كل نوع من هذه الأنواع يقابله نوع صحيح قياسي غير مُؤشّر، هذه الأنواع هي:
</p>

<ul>
<li>
		<code>unsigned char</code>
	</li>
	<li>
		<code>unsigned short int</code>
	</li>
	<li>
		<code>unsigned int</code>
	</li>
	<li>
		<code>unsigned long int</code>
	</li>
	<li>
		<code>unsigned long long int</code>
	</li>
</ul>
<p>
	هذه الأنواع في النهاية لها نفس حجم ومُحاذاة النوع المؤشّر المقابل بالإضافة إلى ذلك، وكما هو مُوضّح في الفقرة 3.9.1.1، النوع <code>‎char‎</code> له نفس متطلّبات <code>‎signed char‎</code> و <code>‎unsigned char‎</code> فيما يخصّ الحجم والمحاذاة.
</p>

<p>
	<strong>الإصدار &lt; C++‎ 11</strong>
</p>

<p>
	قبل الإصدار C++‎ 11، لم يكن <code>‎long long‎</code> و <code>‎unsigned long long‎</code> جزءًا من معيار C++‎. لكن بعد إدخالهما في لغة C في معيار C99، دعمت العديدُ من المصرّفات النوع <code>‎long long‎</code> كنوع عددي صحيح مؤشّر، و <code>unsigned long long</code> كنوع عددي صحيح غير مؤشّر موسّع، له نفس قواعد أنواع C.
</p>

<p>
	يضمن المعيار ما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5072_11" style="">
<span class="lit">1</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="kwd">char</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="kwd">signed</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="kwd">unsigned</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;=</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="kwd">short</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="kwd">unsigned</span><span class="pln"> </span><span class="kwd">short</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;=</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="typ">int</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="kwd">unsigned</span><span class="pln"> </span><span class="typ">int</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;=</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="kwd">long</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="kwd">unsigned</span><span class="pln"> </span><span class="kwd">long</span><span class="pun">)</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<pre class="ipsCode">
&lt;= sizeof(long long) == sizeof(unsigned long long)
</pre>

<p>
	لا ينصّ المعيار على حد أدنى للأحجام لكل نوع على حدة. بدلاً من ذلك، لكلّ نوعٍ من الأنواع مجالًا من الحدود الدنيا التي يمكن أن يدعمها، والتي تكون موروثة على النحو المُوضّح في الفقرة 3.9.1.3 من معيار C، في الفقرة 1.2.4.2.1. ويمكن استنتاج الحد الأدنى لحجم نوع ما من ذلك المجال من خلال تحديد الحد الأدنى لعدد البتّات المطلوبة، لاحظ أنّه في معظم الأنظمة قد يكون المجال المدعوم الفعلي لأيّ نوع أكبر من الحد الأدنى، وأنه في الأنواع المُؤشّرة تتوافق المجالات مع مكمّل (complement) واحد، وليس مع مكمّلين اثنين كما هو شائع؛ وذلك لتسهيل توافق مجموعة واسعة من المنصات مع المعايير.
</p>

<table>
<thead><tr>
<th>
				النوع
			</th>
			<th>
				النطاق الأدنى
			</th>
			<th>
				العدد الأدنى المطلوب للبِتَّات
			</th>
		</tr></thead>
<tbody>
<tr>
<td>
				<code>signed char</code>
			</td>
			<td>
				-127 إلى 127
			</td>
			<td>
				8
			</td>
		</tr>
<tr>
<td>
				<code>unsigned char</code>
			</td>
			<td>
				0 إلى 255
			</td>
			<td>
				8
			</td>
		</tr>
<tr>
<td>
				<code>signed short</code>
			</td>
			<td>
				-32,767 إلى 32,767
			</td>
			<td>
				16
			</td>
		</tr>
<tr>
<td>
				<code>unsigned short</code>
			</td>
			<td>
				0 إلى 65,535
			</td>
			<td>
				16
			</td>
		</tr>
<tr>
<td>
				<code>signed int</code>
			</td>
			<td>
				-32,767 إلى 32,767
			</td>
			<td>
				16
			</td>
		</tr>
<tr>
<td>
				<code>unsigned int</code>
			</td>
			<td>
				0 إلى 65,535
			</td>
			<td>
				16
			</td>
		</tr>
<tr>
<td>
				<code>signed long</code>
			</td>
			<td>
				-2,147,483,647 إلى 2,147,483,647
			</td>
			<td>
				32
			</td>
		</tr>
<tr>
<td>
				<code>unsigned long</code>
			</td>
			<td>
				0 إلى 4,294,967,295
			</td>
			<td>
				32
			</td>
		</tr>
</tbody>
</table>
<style type="text/css">
table {
    width: 100%;
}

thead {
    vertical-align: middle;
    text-align: center;
}

td, th {
    border: 1px solid #dddddd;
    text-align: right;
    padding: 8px;
    text-align: inherit;

}
tr:nth-child(even) {
    background-color: #dddddd;
}</style>
<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<table>
<thead><tr>
<th>
				النوع
			</th>
			<th>
				النطاق الأدنى
			</th>
			<th>
				العدد الأدنى المطلوب للبِتَّات
			</th>
		</tr></thead>
<tbody>
<tr>
<td>
				<code>signed long long</code>
			</td>
			<td>
				-9,223,372,036,854,775,807 إلى 9,223,372,036,854,775,807
			</td>
			<td>
				64
			</td>
		</tr>
<tr>
<td>
				<code>unsigned long long</code>
			</td>
			<td>
				0 إلى 18,446,744,073,709,551,615
			</td>
			<td>
				64
			</td>
		</tr>
</tbody>
</table>
<p>
	قد تختلف أحجام الأنواع من تنفيذ لآخر بما أنه يُسمح للأنواع أن تكون أكبر من الحد الأدنى لمتطلّبات الحجم، وأبرز مثال على ذلك تجده في نموذَجي البيانات المخزّنة على 64 بتّة: LP64 و LLP64، إذ أنّه في أنظمة LLP64 (مثل Windows 64-bit)، فإنّ الأنواع <code>‎ints‎</code> و <code>‎long‎</code> تُخزّن على 32 بتّة (32-bit)، وفي LP64 (مثل 64-bit Linux)، فإنّ <code>‎int‎</code> مخزّنة على 32 بتّة، أمّا <code>‎long‎</code> فمُخزّنة على 64 بتّة. لهذا من الخطأ افتراض أنّ أنواع الأعداد الصحيحة لها نفس الحجم في جميع الأنظمة.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	إذا كانت هناك حاجة إلى أنواع عددية صحيحة ذات أحجام ثابتة فاستخدم أنواعًا من الترويسة <cstdint>، لكن لاحظ أنّ المعيار لا يجبر التنفيذ (implementations) على دعم الأنواع ذات الحجم المضبوط:</cstdint></p>

<ul>
<li>
		<cstdint><code>‎int8_t‎</code></cstdint>
</li>
	<li>
		<cstdint><code>‎int16_t‎</code></cstdint>
</li>
	<li>
		<cstdint><code>‎int32_t‎</code></cstdint>
</li>
	<li>
		<cstdint><code>‎int64_t‎</code></cstdint>
</li>
	<li>
		<cstdint><code>‎intptr_t‎</code></cstdint>
</li>
	<li>
		<cstdint><code>‎uint8_t‎</code></cstdint>
</li>
	<li>
		<cstdint><code>‎uint16_t‎</code></cstdint>
</li>
	<li>
		<cstdint><code>‎uint32_t‎</code></cstdint>
</li>
	<li>
		<cstdint><code>‎uint64_t‎</code></cstdint>
</li>
	<li>
		<cstdint><code>‎uintptr_t‎</code></cstdint>
</li>
</ul>
<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<h3>
	حجم char16_t‎ و char32_t‎
</h3>

<p>
	يتعلق حجم <code>‎char16_t‎</code> و <code>‎char32_t‎</code> بالتنفيذ كما ينصّ على ذلك المعيار في الفقرة 5.3.3.1، مع الشروط الواردة في الفقرة 3.9.1.5:
</p>

<ul>
<li>
		<code>‎char16_t‎</code> كبير بما يكفي لتمثيل أيّ وحدة رمز من UTF-16، كما أنّ له نفس الحجم والإشارة والمحاذاة التي للنوع <code>‎uint_least16_t‎</code>، وعليه فحجمه يساوي 16 بتّة على الأقل.
	</li>
	<li>
		<code>‎char32_t‎</code> كبير بما يكفي لتمثيل أي وحدة رمز في UTF-32، كما أنّ له نفس الحجم والإشارة والمحاذاة التي للنوع <code>‎uint_least32_t‎</code>، وعليه فيجب أن يساوي حجمه 32 بتّة على الأقل.
	</li>
</ul>
<h3>
	حجم bool
</h3>

<p>
	يتعلق حجم <code>‎bool‎</code> بالتنفيذ، ولا يساوي بالضرورة <code>‎1‎</code>.
</p>

<h3>
	حجم wchar_t
</h3>

<p>
	<code>‎wchar_t‎</code>، كما هو مُوضّح في الفقرة 3.9.1.5 هو نوع متميّز إذ يمكن أن يمثّل مجال قيمه كل وحدات الرموز (code unit) في أكبر مجموعة محارف موسّعة من بين اللغات المدعومة، وله نفس الحجم والإشارة والمحاذاة لأحد الأنواع العددية الصحيحة الأخرى، والذي يمثّل نوعه الأساسي (underlying type).
</p>

<p>
	يتعلق حجم هذا النوع بالتنفيذ كما هو مُعرَّف في الفقرة 5.3.3.1، وقد يساوي على سبيل المثال 8 أو 16 أو 32 بتّة على الأقل؛ وإذا كان النظام يدعم اليونيكود فينبغي أن يُخزّن النوع <code>‎wchar_t‎</code> على 32 بتّة على الأقل (باستثناء Windows، إذ يُخزّن النّوع <code>‎wchar_t‎</code> على 16 بتّة لأغراض التوافق). وهو موروث من معيار C90، في ISO 9899: 1990 الفقرة 4.1.5، لكن مع بعض التعديلات البسيطة.
</p>

<p>
	ويساوي حجم <code>‎wchar_t‎</code> غالبًا 8 أو 16 أو 32 بتّة، وذلك حسب التنفيذ. مثلًا:
</p>

<ul>
<li>
		في أنظمة يونكس والأنظمة المشابهة لها، تُخزّن <code>‎wchar_t‎</code> على 32 بتّة، وعادة ما تستخدم في UTF-32.
	</li>
	<li>
		في ويندوز، تُخزّن <code>‎wchar_t‎</code> على 16 بتّة، وتُستخدم مع UTF-16.
	</li>
	<li>
		على الأنظمة التي لا تدعم إلّا 8 بتّات فقط، تُخزّن <code>‎wchar_t‎</code> على 8 بتّات.
	</li>
</ul>
<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	إذا كنت تريد دعم اليونيكود، فإنّه يُوصى باستخدام <code>‎char‎</code> لأجل الترميز UTF-8، و <code>‎char16_t‎</code> لأجل الترميز UTF-16، و <code>‎char32_t‎</code> لأجل الترميز UTF-32، بدلاً من استخدام <code>‎wchar_t‎</code>.
</p>

<h3>
	نماذج البيانات
</h3>

<p>
	يمكن أن تختلف أحجام أنواع الأعداد الصحيحة بين المنصات كما ذكرنا أعلاه، وما يلي هي أكثر النماذج شيوعًا (الأحجام محسوبة بالبتّات):
</p>

<table>
<thead><tr>
<th>
				النموذج
			</th>
			<th>
				<code>int</code>
			</th>
			<th>
				<code>long</code>
			</th>
			<th>
				مؤشر
			</th>
		</tr></thead>
<tbody>
<tr>
<td>
				LP32 (2/4/4)
			</td>
			<td>
				16
			</td>
			<td>
				32
			</td>
			<td>
				32
			</td>
		</tr>
<tr>
<td>
				ILP32 (4/4/4)
			</td>
			<td>
				32
			</td>
			<td>
				32
			</td>
			<td>
				32
			</td>
		</tr>
<tr>
<td>
				LLP64 (4/4/8)
			</td>
			<td>
				32
			</td>
			<td>
				32
			</td>
			<td>
				64
			</td>
		</tr>
<tr>
<td>
				LP64 (4/8/8)
			</td>
			<td>
				32
			</td>
			<td>
				64
			</td>
			<td>
				64
			</td>
		</tr>
</tbody>
</table>
<p>
	من بين هذه النماذج:
</p>

<ul>
<li>
		نظام ويندوز 16-بت استخدم LP32.
	</li>
	<li>
		الأنظمة الشبيهة بيونكس مثل يونكس ولينكس ونظام ماك 10 (Mac OSX) وغيرها، ذات معمارية 32 منها، وكذلك نظام ويندوز 32-بت، تستخدم جميعها ILP32.
	</li>
	<li>
		ويندوز ‎‎64-bit يستخدم LLP64.
	</li>
	<li>
		اليونكسات ذات معمارية ‎‎64-bit تستخدم LP64.
	</li>
</ul>
<p>
	لاحظ أنّ هذه النماذج غير مذكورة في المعيار.
</p>

<h2>
	النوع Char قد يكون مُؤشَّرًا أو لا
</h2>

<p>
	لا ينصّ المعيار على وجوب أن يكون النوع <code>‎char‎</code> مؤشَّرًا من عدمه، لذا فإنّّ كل مصرّف ينفذه بشكل مختلف، أو قد يسمح بتعديله باستخدام سطر الأوامر.
</p>

<h2>
	مجالات الأنواع العددية
</h2>

<p>
	تتعلّق مجالات أنواع الأعداد الصحيحة بالتنفيذ، كما توفّر الترويسة <limits> قالب <code>std::numeric_limits&lt;T&gt;‎‎</code> الذي يوفّر الحدّين الأدنى والأقصى لقيم جميع الأنواع الأساسية. </limits></p>

<p>
	تفي القيم بالضمانات التي يحدّدها معيار C عبر الترويسات <climits> و C++‎ 11 ‎‎‎‎‎‎&lt;=‎‎ ) &lt;cinttypes)</climits></p>

<ul>
<li>
		<code>std::numeric_limits&lt;signed char&gt;::min()‎‎</code> - تساوي <code>SCHAR_MIN</code>، وهي أصغر من أو تساوي ‎‎-127.
	</li>
	<li>
		<code>‎</code>std::numeric_limits<signed char="">::max()‎ تساوي <code>SCHAR_MAX</code>، وهي أكبر من أو تساوي 127.</signed>
</li>
	<li>
		<signed char=""><code>std::numeric_limits&lt;unsigned char&gt;::max()‎‎</code> تساوي <code>UCHAR_MAX</code>، وهي أكبر من أو تساوي 255. </signed>
</li>
	<li>
		<code>std::numeric_limits&lt;short&gt;::min()‎‎</code> تساوي <code>SHRT_MIN</code>، وهي أصغر من ‎‎-32767 أو تساويها.
	</li>
	<li>
		<code>std::numeric_limits&lt;short&gt;::max()‎‎</code> تساوي <code>SHRT_MAX</code>، وهي أكبر من أو تساوي 32767.
	</li>
	<li>
		<code>std::numeric_limits&lt;unsigned short&gt;::max()‎‎</code> تساوي<code>USHRT_MAX</code>، وهي أكبر من أو تساوي 65535.
	</li>
	<li>
		<code>std::numeric_limits&lt;int&gt;::min()</code> تساوي <code>INT_MIN</code>، وهي أصغر من ‎‎-32767 أو تساويها.
	</li>
	<li>
		<code>std::numeric_limits&lt;int&gt;::max()‎‎</code> تساوي <code>INT_MAX</code>، وهي أكبر من أو تساوي 32767.
	</li>
	<li>
		‎‎<code>std::numeric_limits&lt;unsigned int&gt;::max()</code>‎ تساوي <code>UINT_MAX</code>، وهي أكبر من أو تساوي 65535.
	</li>
	<li>
		<code>std::numeric_limits&lt;long&gt;::min()‎‎</code> تساوي <code>LONG_MIN</code>، وهي أصغر من أو تساوي ‎‎-2147483647.
	</li>
	<li>
		<code>std::numeric_limits&lt;long&gt;::max()‎‎</code> تساوي <code>LONG_MAX</code>، وهي أكبر من أو تساوي 2147483647.
	</li>
	<li>
		<code>std::numeric_limits&lt;unsigned long&gt;::max()‎‎</code> تساوي ULONG_MAX، وهي أكبر من أو تساوي 4294967295.
	</li>
</ul>
<p>
	‎‎<strong>الإصدار ≥ C++11</strong>
</p>

<ul>
<li>
		<code>std::numeric_limits&lt;long long&gt;::min()‎‎</code> تساوي <code>‎LLONG_MIN‎</code>، وهي أكبر من أو تساوي ‎‎-9223372036854775807.
	</li>
	<li>
		<code>std::numeric_limits&lt;long long&gt;::max()‎‎</code> تساوي <code>‎LLONG_MAX‎</code>، وهي أكبر من أو تساوي 9223372036854775807.
	</li>
	<li>
		<code>std::numeric_limits&lt;unsigned long long&gt;::max()</code> تساوي <code>‎ULLONG_MAX‎</code>، وهي أكبر من أو تساوي 18446744073709551615.
	</li>
</ul>
<p>
	بالنسبة للنوع العشري‏ <code>‎T‎</code>، فإنّّ <code>‎max()‎</code> تمثّل القيمة المنتهية (finite) القصوى، بينما تمثّل <code>‎min()‎</code> الحدّ الأدنى للقيمة المُوحّدة الموجبة.
</p>

<p>
	تمّ توفير بعض الأعضاء الإضافيين للأنواع العشرية، وهي متعلّقة بالتنفيذ أيضًا، ولكنّها تلبّي بعض الضمانات التي يحدّدها المعيار C عبر الترويسة <cfloat>. </cfloat></p>

<ul>
<li>
		يعيد <code>‎digits10‎</code> عدد الأرقام العشرية الخاصّة بالدقة.
	</li>
	<li>
		<code>std::numeric_limits&lt;float&gt;::digits10</code> تساوي <code>FLT_DIG</code>، والتي لا تقلّ عن 6.
	</li>
	<li>
		<code>std::numeric_limits&lt;double&gt;::digits10</code> تساوي <code>DBL_DIG</code>، والتي لا تقلّ عن 10.
	</li>
	<li>
		<code>‎‎std::numeric_limits&lt;long double&gt;::digits10</code> تساوي <code>LDBL_DIG</code>، والتي لا تقلّ عن 10.
	</li>
	<li>
		العضو <code>‎min_exponent10‎</code> هو الحد الأدنى السلبي E بحيث يكون 10 أسّ E طبيعيًّا.
	</li>
	<li>
		<code>std::numeric_limits&lt;float&gt;::min_exponent10</code> تساوي <code>‎FLT_MIN_10_EXP‎</code>، والتي يساوي على الأكثر ‎‎-37.
	</li>
	<li>
		<code>std::numeric_limits&lt;double&gt;::min_exponent10</code> تساوي <code>‎DBL_MIN_10_EXP‎</code>، والتي تساوي على الأكثر ‎‎-37.
	</li>
	<li>
		<code>std::numeric_limits&lt;long double&gt;::min_exponent10</code> تساوي <code>‎LDBL_MIN_10_EXP‎</code>، والتي تساوي على الأكثر ‎‎-37.
	</li>
	<li>
		العضو <code>‎max_exponent10‎</code> هو الحد الأقصى E بحيث يكون 10 أسّ E منتهيًا (finite).
	</li>
	<li>
		<code>std::numeric_limits&lt;float&gt;::max_exponent10</code> يساوي <code>‎FLT_MIN_10_EXP‎</code>، ولا يقل عن 37.
	</li>
	<li>
		<code>std::numeric_limits&lt;double&gt;::max_exponent10</code> يساوي <code>‎DBL_MIN_10_EXP‎</code>، ولا يقل عن 37.
	</li>
	<li>
		<code>std::numeric_limits&lt;long double&gt;::max_exponent10</code> تساوي <code>‎LDBL_MIN_10_EXP‎</code>، ولا يقل عن37.
	</li>
	<li>
		إذا كان العضو <code>‎is_iec559‎</code> صحيحًا، فإنّّ النوع سيكون مطابقًا للمواصفات IEC 559 / IEEE 754، وبالتالي سيُحدَّد مجاله من قبل المعيار.
	</li>
</ul>
<h2>
	تمثيل قيم الأنواع العشرية
</h2>

<p>
	ينصّ المعيار أن لا تقلّ دقة النوع <code>‎long double‎</code> عن دقة النوع <code>‎double‎</code>، والذي ينبغي ألّا تقل دقّته عن دقّة النوع <code>‎float‎</code>؛ وأنّ النوع <code>‎long double‎</code> ينبغي أن يكون قادرًا على تمثيل أيّ قيمة يمثّلها النوع <code>‎double‎</code>، وأن يمثّل <code>‎double‎</code> أيّ قيمة يمكن أن يمثّلها النوع <code>‎float‎</code>، أما تفاصيل التمثيل فتتعلّق بالتنفيذ.
</p>

<p>
	وبالنسبة لنوع عشري <code>‎T‎</code>، فإنّّ <code>‎std::numeric_limits&lt;T&gt;::radix‎</code> تحدّد الجذر المُستخدم في تمثيل <code>‎T‎</code>، وإذا كانت <code>‎std::numeric_limits&lt;T&gt;::is_iec559‎</code> صحيحة، فإنّّ تمثيل <code>‎T‎</code> يطابق أحد التنسيقات المُعرَّفة من قبل معيار IEC 559 / IEEE 754.
</p>

<h2>
	التدفق الزائد عند التحويل من عدد صحيح إلى غد صحيح مُؤشّر
</h2>

<p>
	عند تحويل عدد صحيح مؤشّر أو غير مؤشّر إلى نوع عددي صحيح مؤشّر ولا تكون قيمته قابلة للتمثيل في النوع المقصود، فإنّّ القيمة المُنتجة تتعلّق بالتنفيذ. مثلًا، لنفرض أن مجال النوع <code>signed char</code> في هذا التنفيذ يكون [-128,127]، ومجال النوع <code>unsigned char</code> من 0 حتى 255:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5072_13" style="">
<span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">12345</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">signed</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> sc </span><span class="pun">=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">    </span><span class="com">// معرفة بالتنفيذ sc قيمة</span><span class="pln">
</span><span class="kwd">unsigned</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> uc </span><span class="pun">=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">    </span><span class="com">// مهيأة عند القيمة 57 uc </span></pre>

<h2>
	النوع الأساسي وحجم التعدادات
</h2>

<p>
	إذا لم يكن النوع الأساسي (underlying type) لنوع <a data-ss1617023048="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-35-%D8%A7%D9%84%D8%AA%D9%83%D8%B1%D8%A7%D8%B1-iteration-%D9%88%D8%A7%D9%84%D8%AA%D8%B9%D8%AF%D8%A7%D8%AF-enumeration-%D9%81%D9%8A-cpp-r956/" rel="">تعدادي</a> مُحدّدا بشكل صريح، فإنّّه سيُعرَّف من قبل التنفيذ.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5072_15" style="">
<span class="kwd">enum</span><span class="pln"> E
</span><span class="pun">{</span><span class="pln">
    RED</span><span class="pun">,</span><span class="pln">
    GREEN</span><span class="pun">,</span><span class="pln">
    BLUE</span><span class="pun">,</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> T </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">underlying_type</span><span class="pun">&lt;</span><span class="pln">E</span><span class="pun">&gt;::</span><span class="pln">type</span><span class="pun">;</span><span class="pln">    </span><span class="com">// يعرِّفه التنفيذ</span></pre>

<p>
	ومع ذلك، فإنّّ المعيار ينصّ على ألّا يكون نوع التعداد الأساسي أكبر من <code>‎int‎</code> إلّا إن لم يكن النوعان <code>‎int‎</code> و <code>‎unsigned‎</code> <code>‎int‎</code> قادريْن على تمثيل جميع قيم التعداد. لذلك في الشيفرة أعلاه، النوع <code>T</code> يمكن أن يكون <code>‎int‎</code> أو <code>‎unsigned int‎</code> أو <code>‎short‎</code> ولكن ليس <code>‎long long‎</code> مثلًا. لاحظ أنّ التعداد له نفس حجم نوعه الأساسي (كما يعيده التابع <code>‎sizeof‎</code>).
</p>

<h2>
	القيمة العددية لمؤشر
</h2>

<p>
	نتيجة تحويل مؤشّر إلى عدد صحيح باستخدام <code>‎reinterpret_cast‎</code> تتعلّق بالتنفيذ، لكن "… يُهدف إلى ألا تكون النتيجة مفاجئة للمطوّرين الذين يعرفون نظام العنونة في الجهاز."
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5072_17" style="">
<span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">x</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">long</span><span class="pln"> addr </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">reinterpret_cast</span><span class="str">&lt;long&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">p</span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> addr </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">    </span><span class="com">// طبع رقم عنوان</span></pre>

<p>
	وبالمثل، فإنّّ المُؤشر الناتج عن تحويل عدد صحيح يكون أيضًا متعلّقًا بالتنفيذ، والطريقة الصحيحة لتخزين مؤشّر كعدد صحيح هي استخدام النوعين <code>‎uintptr_t‎</code> أو <code>‎intptr_t‎</code>، انظر المثال التالي حيث لم يكن <code>uintptr_t</code> في C++03 وإنما في C99، كنوع اختياري في الترويسة <stdint.h>:</stdint.h></p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5072_19" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;stdint.h&gt;</span><span class="pln">

</span><span class="typ">uintptr_t</span><span class="pln"> uip</span><span class="pun">;</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong> يوجد <code>std::uintptr_t</code> اختياري في C++11:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5072_21" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;cstdint&gt;</span><span class="pln">

std</span><span class="pun">::</span><span class="typ">uintptr_t</span><span class="pln"> uip</span><span class="pun">;</span></pre>

<p>
	تُحيل C++‎ 11 إلى C99 لتعريف <code>‎uintptr_t‎</code> (المعيار C99، ‏6.3.2.3):
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		يتميّز النوع العددي الصحيح غير المُؤشّر، بإمكانية تحويل أيّ مؤشّر صالح يشير إلى <code>‎void‎</code> إليه، ثم إعادة تحويله مرّة أخرى إلى مؤشّر إلى <code>‎void‎</code>، وتكون النتيجة مساوية للمؤشّر الأصلي.
	</p>
</blockquote>

<p>
	بالنسبة لغالبية المنصات الحديثة، يمكنك أن تفترض أنّ مساحة العنونة (address space) مسطحة وأنّ الحسابيات على <code>‎uintptr_t‎</code> تكافئ الحسابيات على <code>‎char *‎</code>، ومن الممكن أن يجري التنفيذ أيّ تعديل عند تحويل <code>‎void *‎</code> إلى <code>‎uintptr_t‎</code> طالما أنّه يمكن عكس التعديل عند التحويل من <code>‎uintptr_t‎</code> إلى <code>‎void *‎</code>.
</p>

<h3>
	مسائل تقنية
</h3>

<ul>
<li>
		في الأنظمة المتوافقة مع XSI ‏(X/Open System Interfaces)، فإنّّ النوعين <code>‎intptr_t‎</code> و <code>‎uintptr_t‎</code> إلزاميان، أمّا في الأنظمة الأخرى فهما اختياريان.
	</li>
	<li>
		الدوال ليست كائنات ضمن معيار C، ولا يضمن معيار C أنّ <code>‎uintptr_t‎</code> يستطيع تخزين مؤشّر دالة. كذلك يتطّلب التوافق مع POSIX ‏(2.12.3) أنّ:
	</li>
</ul>
<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		يجب أن يكون لجميع أنواع مؤشّرات الدوالّ نفس تمثيل مؤشّر النوع الذي يشير إلى void، وينبغي ألا يغير تحويل مؤشّر دالّة إلى void *‎‎ التمثيل، ويمكن إعادة تحويل قيمة void *‎ الناتجة عن هذا التحويل إلى نوع مؤشّر الدالّة الأصلي، وذلك باستخدام تحويل صريح، دون الخشية من خسارة أيّ معلومات.
	</p>
</blockquote>

<p>
	معيار C99 الفقرة 7.18.1:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		عندما تختلف typedef في غياب أو وجود الحرف الأوّل u، فيجب أن تشير إلى الأنواع المُؤشّرة وغير المُؤشّرة المقابلة كما هو مُوضّح في الفقرة 6.2.5؛ وأيّ تنفيذ يوفّر أحد هذين النوعين ينبغي أن يوفّر أيضًا النوع المقابل لآخر.
	</p>
</blockquote>

<p>
	قد يكون <code>‎uintptr_t‎</code> مناسبًا إذا كنت تريد العمل على بتّات المؤشّر بشكل قد يتعذّر في حال استخدمت عددًا صحيحًا مؤشّرًا.
</p>

<h2>
	عدد البتات في البايت
</h2>

<p>
	البايت (byte) في C++‎ هو المساحة التي يشغلها كائن <code>‎char‎</code>، وعدد البتات في البايت مُحدّد في <code>‎CHAR_BIT‎</code>، ومُعرّف في <code>‎climits‎</code> ولا يقل عن 8. وفي حين أن عدد بتّات البايت في معظم الأنظمة الحديثة هو 8 وأن أنظمة POSIX تتطلّب أن يساوي <code>‎CHAR_BIT‎</code> القيمة 8 بالضبط، إلا أنّ هناك بعض الأنظمة التي يكون فيها <code>‎CHAR_BIT‎</code> أكبر من 8، فقد يساوي مثلًا 8 أو 16 أو 32 أو 64 بتّة.
</p>

<p>
	هذا الدرس جزء من <a data-ss1617023048="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 71: Implementation-defined behavior من كتاب <a data-ss1617023048="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">958</guid><pubDate>Sat, 22 Aug 2020 18:07:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62A;&#x639;&#x628;&#x64A;&#x631;&#x627;&#x62A; &#x627;&#x644;&#x646;&#x645;&#x637;&#x64A;&#x629; Regular expressions &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AA%D8%B9%D8%A8%D9%8A%D8%B1%D8%A7%D8%AA-%D8%A7%D9%84%D9%86%D9%85%D8%B7%D9%8A%D8%A9-regular-expressions-%D9%81%D9%8A-cpp-r957/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_08/36.png.59bd6dc18d606bde81c959aadf250036.png" /></p>

<p>
	التعبيرات النمطية (تُسمّى أحيانًا regexs أو regexps) هي صِيغ نصّية تمثّل الأنماط التي يمكن مطابقتها في السلاسل النصّية، وقد تدعم التعبيرات النمطيّة التي قُدِّمت في C++‎ 11 -اختياريًا- إعادة مصفوفة من السلاسل النصّية المطابِقة، أو صيغة نصّية أخرى تحدّد كيفيّة استبدال الأنماط المتطابقة في السلاسل النصية.
</p>

<p>
	الصياغة الأولى للدالة <code>regex_match</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2378_8" style="">
<span class="kwd">bool</span><span class="pln"> regex_match</span><span class="pun">(</span><span class="typ">BidirectionalIterator</span><span class="pln"> first</span><span class="pun">,</span><span class="pln"> </span><span class="typ">BidirectionalIterator</span><span class="pln"> last</span><span class="pun">,</span><span class="pln"> smatch</span><span class="pun">&amp;</span><span class="pln"> sm</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> regex</span><span class="pun">&amp;</span><span class="pln"> re</span><span class="pun">,</span><span class="pln"> regex_constraints</span><span class="pun">::</span><span class="pln">match_flag_type flags</span><span class="pun">)</span></pre>

<p>
	يمثّل <code>BidirectionalIterator</code> أيَّ <a data-ss1617023049="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-8-%D8%A7%D9%84%D9%85%D9%83%D8%B1%D8%A7%D8%B1%D8%A7%D8%AA-iterators-%D9%81%D9%8A-cpp-r892/" rel="">مُكرّر</a> محارف يوفّر عامليْ الزيادة (increment) والإنقَاص (decrement). والوسيط <code>smatch</code> يمكن أن يكون كائنًا <code>‎cmatch‎</code> أو أيّ متغيّر آخر من الصنف <code>‎match_results‎</code> يقبل النوع <code>‎BidirectionalIterator‎</code>، ويمكن حذف هذا الوسيط إذا لم تكن بحاجة إلى إعادة نتائج التعبير النمطي. <strong>وتعيد</strong> ما إذا كان التعبير <code>‎re‎</code> يطابق كامل تسلسل المحارف المُعُرّف بواسطة <code>‎first‎</code> و <code>‎last‎</code>.
</p>

<p>
	الصياغة الثانية للدالة <code>regex_match</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2378_10" style="">
<span class="kwd">bool</span><span class="pln"> regex_match</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> string</span><span class="pun">&amp;</span><span class="pln"> str</span><span class="pun">,</span><span class="pln"> smatch</span><span class="pun">&amp;</span><span class="pln"> sm</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> regex re</span><span class="pun">&amp;,</span><span class="pln"> regex_constraints</span><span class="pun">::</span><span class="pln">match_flag_type flags</span><span class="pun">)</span></pre>

<p>
	قد تكون <code>string</code> من النّوع <code>‎const char*‎</code> أو قيمة نصّية يسارية، وتُحذَف الدوالّ التي تقبل سلسلة نصيّة يمينية R- بشكل صريح. الوسيط <code>smatch</code> يمكن أن يكون كائنًا <code>‎cmatch‎</code> أو أيّ متغيّر آخر من الصنف <code>‎match_results‎</code> يقبل سلسلة نصية. ويمكن حذف الوسيط <code>‎smatch‎</code> إذا لم تكن بحاجة إلى إعادة نتائج التعبير النمطي .تعيد الدالة <code>regex_match</code> ما إذا كان التعبير <code>‎re‎</code> قد طابق كامل السلسلة النصية <code>str</code>.
</p>

<h2>
	أمثلة عن regex_match و<em> </em>regex_search
</h2>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2378_12" style="">
<span class="pun">﻿</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> input </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Some people, when confronted with a problem, think \"I know, I'll use regular expressions.\""</span><span class="pln">s</span><span class="pun">;</span><span class="pln">
smatch sm</span><span class="pun">;</span><span class="pln">
cout </span><span class="pun">&lt;&lt;</span><span class="pln"> input </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span></pre>

<p>
	إن انتهى <code>input</code> بعلامة تنصيص تحتوي كلمة تبدأ بالكلمة "reg" وكلمة أخرى تبدأ بـ "ex" فالتقط الجزء السابق من input.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2378_14" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">regex_match</span><span class="pun">(</span><span class="pln">input</span><span class="pun">,</span><span class="pln"> sm</span><span class="pun">,</span><span class="pln"> regex</span><span class="pun">(</span><span class="str">"(.*)\".*\\breg.*\\bex.*\"\\s*$"</span><span class="pun">)))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> capture </span><span class="pun">=</span><span class="pln"> sm</span><span class="pun">[</span><span class="lit">1</span><span class="pun">].</span><span class="pln">str</span><span class="pun">();</span><span class="pln">

    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\t'</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> capture </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// الخرج: "\tSome people, when confronted with a problem, think\ n ";</span></pre>

<p>
	ابحث في الجزء الملتقط عن "a problem" أو "problems #".
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2378_16" style="">
<span class="pln">    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">regex_search</span><span class="pun">(</span><span class="pln">capture</span><span class="pun">,</span><span class="pln"> sm</span><span class="pun">,</span><span class="pln"> regex</span><span class="pun">(</span><span class="str">"(a|d+)\\s+problems?"</span><span class="pun">)))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> count </span><span class="pun">=</span><span class="pln"> sm</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="str">"a"</span><span class="pln">s </span><span class="pun">?</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> stoi</span><span class="pun">(</span><span class="pln">sm</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]);</span><span class="pln">

        cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\t'</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> count </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">count </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="str">" problems\n"</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="str">" problem\n"</span><span class="pun">);</span><span class="pln"> 
</span><span class="com">// الخرج: --&gt; "\t1 problem\ n "</span><span class="pln">
        cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Now they have "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> count </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" problems.\n"</span><span class="pun">;</span><span class="pln">
 </span><span class="com">// الخرج: "Now they have 2 problems\ n " </span><span class="pln">
</span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	<a data-ss1617023049="1" href="https://ideone.com/nSRXEa" rel="external nofollow">هذا مثال حيّ</a> على ذلك.
</p>

<h2>
	مثال عن مُكرّر التعبيرات النمطية regex_iterator
</h2>

<p>
	تُعد <code>‎regex_iterator‎</code> خيارًا ممتازًا عند معالجة الخرج الملتقَط بشكل متكرر، وسيعيد تحصيل <code>‎regex_iterator‎</code> كائن <code>‎match_result‎</code>، وهذا يفيد في الالتقاطات الشرطية (conditional captures) أو الالتقاطات المترابطة.
</p>

<p>
	لنقل أنّنا نريد تقطيع (tokenize) مقتطف من شيفرة C++‎:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2378_18" style="">
<span class="kwd">enum</span><span class="pln"> TOKENS
</span><span class="pun">{</span><span class="pln">
    NUMBER</span><span class="pun">,</span><span class="pln">
    ADDITION</span><span class="pun">,</span><span class="pln">
    SUBTRACTION</span><span class="pun">,</span><span class="pln">
    MULTIPLICATION</span><span class="pun">,</span><span class="pln">
    DIVISION</span><span class="pun">,</span><span class="pln">
    EQUALITY</span><span class="pun">,</span><span class="pln">
    OPEN_PARENTHESIS</span><span class="pun">,</span><span class="pln">
    CLOSE_PARENTHESIS
</span><span class="pun">};</span></pre>

<p>
	يمكننا تقطيع هذه السلسلة النصّية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2378_20" style="">
<span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> input </span><span class="pun">=</span><span class="pln"> </span><span class="str">"42/2 + -8\t=\n(2 + 2) * 2 * 2 -3"</span><span class="pln">s</span><span class="pun">‎</span></pre>

<p>
	<code>‎</code> باستخدام مكرّر تعبيرات نمطية <code>‎regex_iterator‎</code> على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2378_22" style="">
<span class="typ">vector</span><span class="pun">&lt;</span><span class="pln">TOKENS</span><span class="pun">&gt;</span><span class="pln"> tokens</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> regex re
</span><span class="pun">{</span><span class="pln">
    </span><span class="str">"\\s*(\\(?)\\s*(-?\\s*\\d+)\\s*(\\)?)\\s*(?:(\\+)|(-)|(\\*)|(/)|(=))"</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
for_each</span><span class="pun">(</span><span class="pln">sregex_iterator</span><span class="pun">(</span><span class="pln">cbegin</span><span class="pun">(</span><span class="pln">input</span><span class="pun">),</span><span class="pln"> cend</span><span class="pun">(</span><span class="pln">input</span><span class="pun">),</span><span class="pln"> re</span><span class="pun">),</span><span class="pln"> sregex_iterator</span><span class="pun">(),</span><span class="pln"> </span><span class="pun">[&amp;</span><span class="pln"> </span><span class="pun">](</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">i</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i</span><span class="pun">[</span><span class="lit">1</span><span class="pun">].</span><span class="pln">length</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        tokens</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">OPEN_PARENTHESIS</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    tokens</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">i</span><span class="pun">[</span><span class="lit">2</span><span class="pun">].</span><span class="pln">str</span><span class="pun">().</span><span class="pln">front</span><span class="pun">()</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="str">'-'</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> NEGATIVE_NUMBER </span><span class="pun">:</span><span class="pln"> NON_NEGATIVE_NUMBER</span><span class="pun">);</span><span class="pln">

    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i</span><span class="pun">[</span><span class="lit">3</span><span class="pun">].</span><span class="pln">length</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        tokens</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">CLOSE_PARENTHESIS</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">auto</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> next</span><span class="pun">(</span><span class="pln">cbegin</span><span class="pun">(</span><span class="pln">i</span><span class="pun">),</span><span class="pln"> </span><span class="lit">4</span><span class="pun">);</span><span class="pln">

    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> result </span><span class="pun">=</span><span class="pln"> ADDITION</span><span class="pun">;</span><span class="pln"> it </span><span class="pun">!=</span><span class="pln"> cend</span><span class="pun">(</span><span class="pln">i</span><span class="pun">);</span><span class="pln"> </span><span class="pun">++</span><span class="pln">result</span><span class="pun">,</span><span class="pln"> </span><span class="pun">++</span><span class="pln">it</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">it</span><span class="pun">-&gt;</span><span class="pln">length</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> U</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            tokens</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="pln">TOKENS</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">result</span><span class="pun">));</span><span class="pln">
            </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> </span><span class="pun">});</span><span class="pln">
match_results</span><span class="pun">&lt;</span><span class="pln">string</span><span class="pun">::</span><span class="pln">const_reverse_iterator </span><span class="pun">&gt;</span><span class="pln"> sm</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">regex_search</span><span class="pun">(</span><span class="pln">crbegin</span><span class="pun">(</span><span class="pln">input</span><span class="pun">),</span><span class="pln"> crend</span><span class="pun">(</span><span class="pln">input</span><span class="pun">),</span><span class="pln"> sm</span><span class="pun">,</span><span class="pln"> regex
    </span><span class="pun">{</span><span class="pln">
        tokens</span><span class="pun">.</span><span class="pln">back</span><span class="pun">()</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> SUBTRACTION </span><span class="pun">?</span><span class="pln">
            </span><span class="str">"^\\s*\\d+\\s*-\\s*(-?)"</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="str">"^\\s*\\d+\\s*(-?)"</span><span class="pln"> </span><span class="pun">}))</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    tokens</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">sm</span><span class="pun">[</span><span class="lit">1</span><span class="pun">].</span><span class="pln">length</span><span class="pun">()</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> NON_NEGATIVE_NUMBER </span><span class="pun">:</span><span class="pln"> NEGATIVE_NUMBER</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هذا <a data-ss1617023049="1" href="https://ideone.com/Rv5WNI" rel="external nofollow">مثال حيّ</a>.
</p>

<p>
	ينبغي أن يكون وسيط <code>‎regex‎</code> قيمة يسارية (L-value)، إذ أنّ <a data-ss1617023049="1" href="https://stackoverflow.com/questions/29895747/visual-studio-regex-iterator-bug" rel="external nofollow">القيم اليمينيّة</a> لن تعمل.
</p>

<h2>
	المراسي (Anchors)
</h2>

<p>
	توفّر C++‎ أربع مراسي فقط:
</p>

<ul>
<li>
		<code>‎^‎</code> - تمثّل بداية السلسلة النصّية
	</li>
	<li>
		<code>‎$‎</code> - تمثّل نهاية السلسلة النصّية
	</li>
	<li>
		<code>‎\b‎</code> - تمثّل محرف <code>‎\W‎</code> أو بداية أو نهاية السلسلة النصّية.
	</li>
	<li>
		<code>‎\B‎</code> - تمثّل محرف <code>‎\w‎</code>.
	</li>
</ul>
<p>
	في المثال التالي سنحاول التقاط عددٍ مع إشارَتِه:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2378_24" style="">
<span class="kwd">auto</span><span class="pln"> input </span><span class="pun">=</span><span class="pln"> </span><span class="str">"+1--12 * 123/+1234"</span><span class="pln">s</span><span class="pun">;</span><span class="pln">
smatch sm</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">regex_search</span><span class="pun">(</span><span class="pln">input</span><span class="pun">,</span><span class="pln"> sm</span><span class="pun">,</span><span class="pln"> regex
    </span><span class="pun">{</span><span class="pln">
        </span><span class="str">"(?:^|\\b\\W)([+-]?\\d+)"</span><span class="pln"> </span><span class="pun">}))</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">do</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        cout </span><span class="pun">&lt;&lt;</span><span class="pln"> sm</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
        input </span><span class="pun">=</span><span class="pln"> sm</span><span class="pun">.</span><span class="pln">suffix</span><span class="pun">().</span><span class="pln">str</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">regex_search</span><span class="pun">(</span><span class="pln">input</span><span class="pun">,</span><span class="pln"> sm</span><span class="pun">,</span><span class="pln"> regex
        </span><span class="pun">{</span><span class="pln">
            </span><span class="str">"(?:^\\W|\\b\\W)([+-]?\\d+)"</span><span class="pln"> </span><span class="pun">}));</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هذا <a data-ss1617023049="1" href="https://ideone.com/uE4dGr" rel="external nofollow">مثال حيّ</a>
</p>

<p>
	لاحظ أنّ المرساة لا تستهلك أيّ محرف.
</p>

<h2>
	مثال على استخدام regex_replace
</h2>

<p>
	تأخذ هذه الشيفرة عدّة أنماط من الأقواس، وتعيد تنسيقها إلى نمط K&amp;R أو كيرنيجان وريتشي (إشارة إلى أسلوب الأقواس المستخدم في نواة يونكس الأولى).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2378_26" style="">
<span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> input </span><span class="pun">=</span><span class="pln"> </span><span class="str">"if (KnR)\n\tfoo();\nif (spaces) {\n foo();\n}\nif (allman)\n{\n\tfoo();\n}\nif (horstmann)\n{\tfoo();\n}\nif (pico)\n{\tfoo(); }\nif (whitesmiths)\n\t{\n\tfoo();\n\t}\n"</span><span class="pln">s</span><span class="pun">;</span><span class="pln">

cout </span><span class="pun">&lt;&lt;</span><span class="pln"> input </span><span class="pun">&lt;&lt;</span><span class="pln"> regex_replace</span><span class="pun">(</span><span class="pln">input</span><span class="pun">,</span><span class="pln"> regex</span><span class="pun">(</span><span class="str">"(.+?)\\s*\\{?\\s*(.+?;)\\s*\\}?\\s*"</span><span class="pun">),</span><span class="pln"> </span><span class="str">"$1{\n\t$2\n}\n"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span></pre>

<p>
	<a data-ss1617023049="1" href="https://ideone.com/ICR5wM" rel="external nofollow">مثال حيّ</a>.
</p>

<h2>
	مثال على استخدام regex_token_iterator
</h2>

<p>
	<code>‎std::regex_token_iterator‎</code> هي أداة مفيدة للغاية لاستخراج عناصر من ملف يحتوي قيمًا مفصولة بفواصل، كما أنّها قادرة أيضًا على التقاط الفواصل، على خلاف الطرق الأخرى التي تجد صعوبة في ذلك:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2378_28" style="">
<span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> input </span><span class="pun">=</span><span class="pln"> </span><span class="str">"please split,this,csv, ,line,\\,\n"</span><span class="pln">s</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> regex re</span><span class="pun">{</span><span class="pln"> </span><span class="str">"((?:[^\\\\,]|\\\\.)+)(?:,|$)"</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">vector</span><span class="str">&lt;string&gt;</span><span class="pln"> m_vecFields</span><span class="pun">{</span><span class="pln"> sregex_token_iterator</span><span class="pun">(</span><span class="pln">cbegin</span><span class="pun">(</span><span class="pln">input</span><span class="pun">),</span><span class="pln"> cend</span><span class="pun">(</span><span class="pln">input</span><span class="pun">),</span><span class="pln"> re</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">),</span><span class="pln">
sregex_token_iterator</span><span class="pun">()</span><span class="pln"> </span><span class="pun">};</span><span class="pln">

cout </span><span class="pun">&lt;&lt;</span><span class="pln"> input </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">

copy</span><span class="pun">(</span><span class="pln">cbegin</span><span class="pun">(</span><span class="pln">m_vecFields</span><span class="pun">),</span><span class="pln"> cend</span><span class="pun">(</span><span class="pln">m_vecFields</span><span class="pun">),</span><span class="pln"> ostream_iterator</span><span class="str">&lt;string&gt;</span><span class="pun">(</span><span class="pln">cout</span><span class="pun">,</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">));</span></pre>

<p>
	<a data-ss1617023049="1" href="https://ideone.com/lySlTJ" rel="external nofollow">مثال حي</a>.
</p>

<p>
	ينبغي أن يكون الوسيط <code>‎regex‎</code> قيمة يسارية (L-value)، فالقِيم اليمينيّة (R-value) لن تعمل.
</p>

<h2>
	المحدِّدات الكمية
</h2>

<p>
	لنفترض أنّ لدينا سلسلة نصية ثابتة (<code>‎const string input‎</code>) تحتوي رقم هاتف وعلينا أن نتحقّق من صحّته. يمكن أن نبدأ بطلب مدخلات رقمية مع أيّ عدد من المحدِّدات الكمية <code>‎regex_match(input, regex("\\d*"))‎</code>، أو مع محدِّد كمي <code>‎regex_match(input, regex("\\d+"))‎</code> واحد أو أكثر، بيْد أنّ كليهما سيفشلان إذا كانت المدخلات <code>‎input‎</code> تحتوي على سلسلة نصّية رقمية غير صالحة مثل: "123".
</p>

<p>
	سنستخدم n أو أكثر من المحدِّدات الكمية للتحقّق من أنّنا حصلنا على 7 أرقام على الأقل:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2378_30" style="">
<span class="pln">regex_match</span><span class="pun">(</span><span class="pln">input</span><span class="pun">,</span><span class="pln"> regex</span><span class="pun">(</span><span class="str">"\\d{7,}"</span><span class="pun">))</span></pre>

<p>
	سيضمن هذا أنّنا سنحصل على العدد الصحيح من أرقام الهاتف، لكن يمكن أن تحتوي <code>‎input‎</code> أيضًا على سلسلة رقمية أطول ممّا ينبغي مثل: "123456789012"، لذلك فالحلّ هو استخدام محدِّد كمي بين n و m بحيث يكون عدد أحرف <code>‎input‎</code> محصورًا بين 7 و 11 رقمًا
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2378_32" style="">
<span class="pln">regex_match</span><span class="pun">(</span><span class="pln">input</span><span class="pun">,</span><span class="pln"> regex</span><span class="pun">(</span><span class="str">"\\d{7,11}"</span><span class="pun">));</span></pre>

<p>
	هذا أفضل، لكن ما تزال هنا مشكلة، إذ ينبغي أن ننتبه إلى السلاسل الرقمية غير القانونية التي تقع في النطاق [7، 11]، مثل: "123456789"، لذا دعنا نجعل رمز البلد (country code) اختياريًا عبر استخدام محدِّد كمي كسول(lazy quantiﬁer):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2378_34" style="">
<span class="pln">regex_match</span><span class="pun">(</span><span class="pln">input</span><span class="pun">,</span><span class="pln"> regex</span><span class="pun">(</span><span class="str">"\\d?\\d{7,10}"</span><span class="pun">))</span></pre>

<p>
	من المهمّ أن تعلم أنّ المحدِّد الكمي الكسول يحاول مطابقة أقل عدد ممكن من المحارف، وعليه فإنّّ الطريقة الوحيدة للمطابقة هي إذا كانت هناك فعليًا 10 محارف متطابقة مع <code>‎\d{7,10}‎</code>. (لمطابقة الحرف الأول بطمع (greedy)، سيكون علينا استخدام: <code>‎\d{0,1}‎</code>}.) يمكن ضمّ المحدِّد الكمي الكسول (lazy quantifier) إلى أيّ محدِّد كمي آخر.
</p>

<p>
	الآن، كيف يمكننا جعل رمز المنطقة اختياريًا، وعدم قبول رمز الدولة إلّا في حال كان رمز المنطقة موجودًا؟
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2378_36" style="">
<span class="pln">regex_match</span><span class="pun">(</span><span class="pln">input</span><span class="pun">,</span><span class="pln"> regex</span><span class="pun">(</span><span class="str">"(?:\\d{3,4})?\\d{7}"</span><span class="pun">))</span></pre>

<p>
	تتطّلب <code>‎\d{7}‎</code> في هذا التعبير النمطي النهائي سبعة أرقام، ومسبوقة -اختياريًا- إما بثلاثة أو أربعة أرقام. لاحظ أنّنا لم نضم المحدِّد الكسول : <code>‎\d{3,4}?\d{7}‎</code>، إذ أنّ <code>‎\d{3,4}?‎</code> يمكن أن يطابق إمّا 3 أو 4 محارف، بيْد أنّه يُفضّل الاكتفاء بـ 3 محارف، ( لهذا يُسمّونه كسولًا). بدلاً من ذلك، جعلنا المجموعة غير الملتقِطة (non-capturing group) لا تنجح في المُطابقة إلّا مرّة واحدة على الأكثر، مع تفضيل عدم التطابق. وهذا يتسبّب في منع التطابق إذا لم تتضمن <code>‎input‎</code> رمز المنطقة، كما في: "1234567".
</p>

<p>
	أود أن أشير في ختام موضوع المحدِّدات الكمية، إلى محدِّد آخر يمكنك استخدامه، وهو المحدِّد الكمي المُتملِّك (possessive quantiﬁer). كلا المحدِّديْن سواءً المكمّم القنوع أو المكمّم المتملّك، يمكن ضمّهما إلى أيّ مكمّم آخر. وظيفة المكمّم المتملّك الوحيدة هي مساعدة محرّك التعبير النمطي عبر إخباره بأخذ ما أمكن من الأحرف المطابقة وعدم التخلي عنها حتى لو تسبّب ذلك في فشل التعبير النمطي.
</p>

<p>
	على سبيل المثال، التعبير التالي لا معنى له: <code>regex_match(input, regex("\\d{3,4}+\\d{7}))‎‎</code> لأنّ مُدخلًا <code>‎input‎</code> مثل:" 1234567890 " لن يُطابَق بالتعبير <code>‎‎\d{3,4}+‎</code>، وسيُطابق دائمًا بأربعة محارف، حتى لو كانت مطابقة 3 محارف كافية لإنجاح التعبير النمطي.
</p>

<p>
	يُستخدم المحدِّد المتملّك عادة عندما تحدّ الوحدة المحدَّدة كميًا عددَ المحارف القابلة للمطابقة. على سبيل المثال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2378_38" style="">
<span class="pln">regex_match</span><span class="pun">(</span><span class="pln">input</span><span class="pun">,</span><span class="pln"> regex</span><span class="pun">(</span><span class="str">"(?:.*\\d{3,4}+){3}"</span><span class="pun">))</span></pre>

<p>
	يمكن استخدامها إذا كانت <code>‎input‎</code> تحتوي أيًّا ممّا يلي:
</p>

<pre class="ipsCode">
123 456 7890
123-456-7890
(123)456-7890
(123) 456 - 7890
</pre>

<p>
	بيْد أنّ فائدة هذا التعبير النمطي تظهر عندما تتضمّن <code>‎input‎</code> مُدخلاً غير صالح، مثل:
</p>

<pre class="ipsCode">
12345 - 67890
</pre>

<p>
	بدون استخدام المحدِّد الكمي المتملّك، سيتعيّن على محرّك التعبير النمطي الرجوع واختبار كل توليفات ‎‎.*‎<code>‎</code>، سواء مع 3 أو 4 محارف للتحقّق ممّا إن كان يستطيع العثور على تركيبة مطابقة. سيبدأ التعبير النمطي، باستخدام المحدِّد المتملّك، من حيث توقّف المحدِّد المتملّك الثاني، أي المحرف "0"، ثمّ سيحاول محرّك التعبير النمطي ضبط <code>‎.*‎</code> للسماح بمطابقة <code>‎\d{3,4}‎</code>؛ وفي حال تعذّر ذلك سيفشل التعبير النمطي، ولن يرجِع للخلف للتحقّق ممّا إذا كان من الممكن إنجاح المطابقة عبر إعادة ضبط <code>‎.*‎</code> في مرحلة أبكر.
</p>

<h2>
	تقطيع سلسلة نصية Splitting a string
</h2>

<p>
	هذا مثال توضيحيّ على كيفية تقسيم سلسلة نصّية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2378_41" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&gt;</span><span class="pln"> split</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&amp;</span><span class="pln">str</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string regex</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">regex r</span><span class="pun">{</span><span class="pln"> regex </span><span class="pun">};</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">sregex_token_iterator start</span><span class="pun">{</span><span class="pln"> str</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> str</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> r</span><span class="pun">,</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pln"> </span><span class="pun">},</span><span class="pln"> end</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">vector</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&gt;(</span><span class="pln">start</span><span class="pun">,</span><span class="pln"> end</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

split</span><span class="pun">(</span><span class="str">"Some string\t with whitespace "</span><span class="pun">,</span><span class="pln"> </span><span class="str">"\\s+"</span><span class="pun">);</span><span class="pln"> </span><span class="com">// "Some", "string", "with", "whitespace"</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617023049="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 70: Regular expressions من كتاب <a data-ss1617023049="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">957</guid><pubDate>Wed, 19 Aug 2020 18:02:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62A;&#x643;&#x631;&#x627;&#x631; Iteration &#x648;&#x627;&#x644;&#x62A;&#x639;&#x62F;&#x627;&#x62F; Enumeration &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AA%D9%83%D8%B1%D8%A7%D8%B1-iteration-%D9%88%D8%A7%D9%84%D8%AA%D8%B9%D8%AF%D8%A7%D8%AF-enumeration-%D9%81%D9%8A-cpp-r956/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_08/35.png.4ba454405798099f5117b7644b6b72fb.png" /></p>

<h2>
	التكرار Iteration
</h2>

<h3>
	do
</h3>

<p>
	تقدِّم تعليمة <code>do</code> <a data-ss1617022544="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-9-%D8%A7%D9%84%D8%AD%D9%84%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D9%83%D8%B1%D8%A7%D8%B1%D9%8A%D8%A9-loops-%D9%81%D9%8A-cpp-r893/" rel="">حلقة</a> <code>do-while</code>، انظر المثال التالي حيث نحصل على المحرف التالي غير الفارغ من مجرى الدخل القياسي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1691_7" style="">
<span class="kwd">char</span><span class="pln"> read_char</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">char</span><span class="pln"> c</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">do</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        c </span><span class="pun">=</span><span class="pln"> getchar</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">isspace</span><span class="pun">(</span><span class="pln">c</span><span class="pun">));</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> c</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	while
</h3>

<p>
	تقدّم تعليمة <code>while</code> حلقة while.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1691_9" style="">
<span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="com">// اطبع عشر نجمات</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    putchar</span><span class="pun">(</span><span class="str">'*'</span><span class="pun">);</span><span class="pln">
    i</span><span class="pun">++;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	حلقة for النطاقية range-based
</h3>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1691_13" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> primes </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pun">,</span><span class="pln"> </span><span class="lit">11</span><span class="pun">,</span><span class="pln"> </span><span class="lit">13</span><span class="pun">};</span><span class="pln"> 

</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> prime</span><span class="pun">:</span><span class="pln"> primes</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> prime </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	for
</h3>

<p>
	تقدّم تعليمة <code>for</code> حلقة <code>for</code>، يمكن استخدامها في C++‎ 11 والإصدارات الأحدث لتقديم حلقة for النطاقية (range-based for loop).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1691_15" style="">
<span class="com">// اطبع عشر نجمات</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    putchar</span><span class="pun">(</span><span class="str">'*'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	التكرار على تعداد
</h2>

<p>
	ليس هناك حلٌّ مضمَّن مسبقًا للتكرار (iterate) على كائن تعداد (enumeration)، لكن هناك عدة طرق أخرى لذلك:
</p>

<ul>
<li>
		بالنسبة للتعدادات (<code>‎enum‎</code>) ذات القيم المتتالية:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1691_17" style="">
<span class="kwd">enum</span><span class="pln"> E </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Begin</span><span class="pun">,</span><span class="pln">
    E1 </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Begin</span><span class="pun">,</span><span class="pln">
    E2</span><span class="pun">,</span><span class="pln">
    </span><span class="com">// ..</span><span class="pln">
    </span><span class="typ">En</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">End</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">E e </span><span class="pun">=</span><span class="pln"> E</span><span class="pun">::</span><span class="typ">Begin</span><span class="pun">;</span><span class="pln"> e </span><span class="pun">!=</span><span class="pln"> E</span><span class="pun">::</span><span class="typ">End</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// e افعل شيئا ما بـ</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	يجب تنفيذ العامل <code>‎operator ++‎</code> مع <code>‎enum class‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1691_19" style="">
<span class="pln">E</span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">++</span><span class="pln"> </span><span class="pun">(</span><span class="pln">E</span><span class="pun">&amp;</span><span class="pln"> e</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">e </span><span class="pun">==</span><span class="pln"> E</span><span class="pun">::</span><span class="typ">End</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">throw</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">out_of_range</span><span class="pun">(</span><span class="str">"for E&amp; operator ++ (E&amp;)"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    e </span><span class="pun">=</span><span class="pln"> E</span><span class="pun">(</span><span class="kwd">static_cast</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">underlying_type </span><span class="pun">&lt;</span><span class="pln"> E </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">type </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> e</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<ul>
<li>
		استخدام حاوية كمتّجه (<code>‎std::vector‎</code>):
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1691_21" style="">
<span class="kwd">enum</span><span class="pln"> E </span><span class="pun">{</span><span class="pln">
    E1 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln">
        E2 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln">
        </span><span class="com">// ..</span><span class="pln">
        </span><span class="typ">En</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

std</span><span class="pun">::</span><span class="typ">vector</span><span class="pun">&lt;</span><span class="pln">E</span><span class="pun">&gt;</span><span class="pln"> build_all_E</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> E all</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">E1</span><span class="pun">,</span><span class="pln"> E2</span><span class="pun">,</span><span class="pln"> </span><span class="com">/*..*/</span><span class="pln"> </span><span class="typ">En</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">vector</span><span class="pun">&lt;</span><span class="pln">E</span><span class="pun">&gt;(</span><span class="pln">all</span><span class="pun">,</span><span class="pln"> all </span><span class="pun">+</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">all</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">E</span><span class="pun">));</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> E </span><span class="pun">&gt;</span><span class="pln"> all_E </span><span class="pun">=</span><span class="pln"> build_all_E</span><span class="pun">();</span></pre>

<p>
	ثمّ:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1691_23" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="pun">&lt;</span><span class="pln">E</span><span class="pun">&gt;::</span><span class="typ">const_iterator</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> all_E</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">();</span><span class="pln"> it </span><span class="pun">!=</span><span class="pln"> all_E</span><span class="pun">.</span><span class="pln">end</span><span class="pun">();</span><span class="pln"> </span><span class="pun">++</span><span class="pln">it</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    E e </span><span class="pun">=</span><span class="pln"> </span><span class="pun">*</span><span class="pln">it</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// e افعل شيئا ما بـ </span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<ul>
<li>
		أو يمكن استخدام <code>‎std::initializer_list‎</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1691_25" style="">
<span class="kwd">enum</span><span class="pln"> E </span><span class="pun">{</span><span class="pln">
        E1 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln">
        E2 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln">
        </span><span class="com">// ..</span><span class="pln">
        </span><span class="typ">En</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">constexpr</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">initializer_list </span><span class="pun">&lt;</span><span class="pln"> E </span><span class="pun">&gt;</span><span class="pln"> all_E </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span></pre>

<p>
	ثم بعد ذلك:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1691_27" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> e</span><span class="pun">:</span><span class="pln"> all_E</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// e افعل شيئا ما بـ</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	التعدادات النطاقية (Scoped enums)
</h2>

<p>
	قدّمت C++‎ 11 ما يعرف باسم التعداد النطاقي، وهي تعدادات يلزَم تأهيل أعضائها عبر <code>‎enumname::membername‎</code>. ويُصرَّح عن التعدادات النطاقية باستخدام الصيغة <code>‎enum class‎</code>، فمثلًا لتخزين ألوان قوس قزح، نكتب ما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1691_29" style="">
<span class="kwd">enum</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> rainbow </span><span class="pun">{</span><span class="pln">
    RED</span><span class="pun">,</span><span class="pln">
    ORANGE</span><span class="pun">,</span><span class="pln">
    YELLOW</span><span class="pun">,</span><span class="pln">
    GREEN</span><span class="pun">,</span><span class="pln">
    BLUE</span><span class="pun">,</span><span class="pln">
    INDIGO</span><span class="pun">,</span><span class="pln">
    VIOLET
</span><span class="pun">};</span></pre>

<p>
	وللوصول إلى لون معين:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1691_31" style="">
<span class="pln">rainbow r </span><span class="pun">=</span><span class="pln"> rainbow</span><span class="pun">::</span><span class="pln">INDIGO</span><span class="pun">;</span></pre>

<p>
	لا يمكن تحويل أصناف التعدادات (<code>‎enum ‎class‎</code>) ضمنيًا إلى أعداد صحيحة (<code>‎int‎</code>) بدون تحويل النوع (cast). لذلك فإنّ التعبير <code>int x = rainbow::RED</code> غير صالح.
</p>

<p>
	تتيح لك التعدادات النطاقية أيضًا تحديد النوع الأساسي (underlying type)، أي النوع المستخدم لتمثيل العضو. والذي يساوي افتراضيًا النوع <code>‎int‎</code>. مثلًا، في لعبة تيك تاك تو (Tic-Tac-Toe)، يمكنك تخزين القطع كما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1691_33" style="">
<span class="kwd">enum</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> piece</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    EMPTY </span><span class="pun">=</span><span class="pln"> </span><span class="str">'\0'</span><span class="pun">,</span><span class="pln">
        X </span><span class="pun">=</span><span class="pln"> </span><span class="str">'X'</span><span class="pun">,</span><span class="pln">
        O </span><span class="pun">=</span><span class="pln"> </span><span class="str">'O'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	لعلك انتبهت إلى أن التعداد <code>‎enum‎</code> يمكن أن يحتوي فاصلة زائدة بعد العضو الأخير.
</p>

<h2>
	التصريح المسبق عن التعدادات في C++‎ 11
</h2>

<p>
	يمكن التصريح المسبق (forward declaration) عن التعدادات النطاقية على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1691_35" style="">
<span class="pun">...</span><span class="pln">
</span><span class="kwd">enum</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Status</span><span class="pun">;</span><span class="pln"> </span><span class="com">// تصريح مسبق</span><span class="pln">
</span><span class="typ">Status</span><span class="pln"> doWork</span><span class="pun">();</span><span class="pln"> </span><span class="com">// استخدام التصريح المسبق</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
</span><span class="kwd">enum</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Status</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Invalid</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Success</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Fail</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">Status</span><span class="pln"> doWork</span><span class="pun">()</span><span class="pln"> </span><span class="com">// يلزم تصريح كامل لأجل التقديم</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">Status</span><span class="pun">::</span><span class="typ">Success</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	أمّا التعدادات غير النطاقية، فيمكن التصريح عنها مُسبقًا عبر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1691_37" style="">
<span class="pun">...</span><span class="pln">
</span><span class="kwd">enum</span><span class="pln"> </span><span class="typ">Status</span><span class="pun">:</span><span class="pln"> </span><span class="typ">int</span><span class="pun">;</span><span class="pln"> </span><span class="com">// تصريح مسبق،  يلزم نوع صريح</span><span class="pln">
</span><span class="typ">Status</span><span class="pln"> doWork</span><span class="pun">();</span><span class="pln"> </span><span class="com">// استخدام التصريح المسبق</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
</span><span class="kwd">enum</span><span class="pln"> </span><span class="typ">Status</span><span class="pun">:</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Invalid</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Success</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Fail</span><span class="pln">
</span><span class="pun">};</span><span class="pln"> </span><span class="com">// يلزم مطابقة نوع التصريح المسبق</span><span class="pln">
</span><span class="kwd">static_assert</span><span class="pun">(</span><span class="typ">Success</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span></pre>

<p>
	<a data-ss1617022544="1" href="https://stackoverflow.com/questions/19074084/forward-declaring-enum-class-not-working/19074269#19074269" rel="external nofollow">انظر إن شئت مثال "تاجر الفاكهة الأعمى" الأكثر تعقيدًا</a>.
</p>

<h2>
	التصريح بالتعداد Enumeration Declaration
</h2>

<p>
	تسمح التعدادات القياسية للمستخدمين بالتصريح عن اسم يمثّل مجموعة من الأعداد الصحيحة، وتسمى هذه الأسماء مجتمعةً عدّادات (enumerators)، وتُعرّف التِّعدادات والعَدّادات المرتبطة بها على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1691_39" style="">
<span class="kwd">enum</span><span class="pln"> myEnum </span><span class="pun">{</span><span class="pln">
    enumName1</span><span class="pun">,</span><span class="pln">
    enumName2</span><span class="pun">,</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	يعدّ التعداد نوعًا متميزًا عن جميع الأنواع الأخرى، ويكون اسم هذا النوع في المثال أعلاه هو <code>‎myEnum‎</code>، ويُتوقّع أن تُخمِّن كائنات هذا النوع قيمة العدّاد داخل التعداد.
</p>

<p>
	العدّادات المُصرّح عنها ضمن التعداد تكون قيمًا ثابتة من نوع ذلك التعداد، ورغم أنّ العدّادات تُعلَن ضمن النوع، إلا أنّ عامل النطاق - scope operator‏‏ - <code>‎::‎</code> ليس ضروريًا للوصول إلى الاسم. لذلك، فاسم العدّاد الأول سيكون <code>‎enumName1‎</code>.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	يمكن استخدام عامل النطاق -اختياري- للوصول إلى عدّاد داخل التعداد. لذلك، يمكن كتابة <code>‎enumName1‎</code> على النحو التالي <code>‎myEnum::enumName1‎</code>.
</p>

<p>
	وتُسند إلى العدّادات قيم عددية صحيحة تبدأ من 0 وتزداد بـ 1 لكل عدّاد إضافي في التعداد. لذلك في المثال أعلاه، فإنّ قيمة <code>‎enumName1‎</code> تساوي 0، وقيمة <code>‎enumName2‎</code> تساوي 1. كذلك يمكن إسناد قيمة معيّنة إلى العدّادات من قبل المستخدم؛ وعندئذ يجب أن تكون تلك القيمة تعبيرًا عدديًا صحيحًا ثابتًا. أيضًا، سيُسند إلى العدّادات التي لم تُوفّر قيمها صراحة "قيمة العداد السابق + 1".
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1691_43" style="">
<span class="kwd">enum</span><span class="pln"> myEnum </span><span class="pun">{</span><span class="pln">
    enumName1 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="com">//  1 القيمة ستكون</span><span class="pln">
        enumName2 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="com">//  2 القيمة ستكون</span><span class="pln">
        enumName3</span><span class="pun">,</span><span class="pln"> </span><span class="com">//  القيمة ستكون 5، أي القيمة السابقة + 1</span><span class="pln">
        enumName4 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">7</span><span class="pun">,</span><span class="pln"> </span><span class="com">//  7 القيمة ستكون</span><span class="pln">
        enumName5</span><span class="pun">,</span><span class="pln"> </span><span class="com">//  8 القيمة ستكون</span><span class="pln">
        enumName6 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="com">//   القيمة ستكون 5، يجوز العودة إلى الوراء</span><span class="pln">
        enumName7 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="com">//  القيمة ستكون 3، يجوز إعادة استخدام الأعداد</span><span class="pln">
        enumName8 </span><span class="pun">=</span><span class="pln"> enumName4 </span><span class="pun">+</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="com">//  القيمة ستكون 9، يجوز أخذ العدادات السابقة وتعديلها</span><span class="pln">
</span><span class="pun">};</span></pre>

<h2>
	التعدادات في تعليمات <code>switch</code>
</h2>

<p>
	يشيع استخدام العدادات مع عبارات switch، ومن ثمّ فهي تظهر عادة في أجهزة الحالة (state machines). من الميزات المفيدة التي تقدّمها التعدادات في عبارات <code>switch</code> هو أنّه في حال لم تُضمَّن أيّ تعليمة افتراضية في <code>switch</code>، ولم تُستخدم جميع قيم التعداد، فسيُطلِق المصرّف تحذيرًا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1691_45" style="">
<span class="kwd">enum</span><span class="pln"> </span><span class="typ">State</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    start</span><span class="pun">,</span><span class="pln">
    middle</span><span class="pun">,</span><span class="pln">
    end
</span><span class="pun">};</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
</span><span class="kwd">switch</span><span class="pln"> </span><span class="pun">(</span><span class="pln">myState</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">case</span><span class="pln"> start</span><span class="pun">:</span><span class="pln">
    </span><span class="pun">...</span><span class="pln">
</span><span class="kwd">case</span><span class="pln"> middle</span><span class="pun">:</span><span class="pln">
    </span><span class="pun">...</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="com">// warning: enumeration value 'end' not handled in switch [-Wswitch]</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617022544="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -وبتصرّف- للفصل Chapter 68: Enumeration من الكتاب <a data-ss1617022544="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">956</guid><pubDate>Mon, 17 Aug 2020 18:04:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62A;&#x631;&#x62A;&#x64A;&#x628; (Sorting) &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AA%D8%B1%D8%AA%D9%8A%D8%A8-sorting-%D9%81%D9%8A-cpp-r955/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_08/34.png.bb3b3bfd6c79b4296dd8bb0a3c9fb4e9.png" /></p>

<h2>
	الترتيب وحاويات التسلسلات
</h2>

<p>
	<code>std::sort</code> هي خوارزمية لتَرتيب مجموعة من القي، وتوجد في ترويسة المكتبة القياسية <code>‎algorithm‎</code>، وهي مُعرّفة بواسطة زوج من <a data-ss1617022542="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-8-%D8%A7%D9%84%D9%85%D9%83%D8%B1%D8%A7%D8%B1%D8%A7%D8%AA-iterators-%D9%81%D9%8A-cpp-r892/" rel="">المُكرّرات</a>. وتأخذ <code>‎std::sort‎</code> كائنًا داليًّا كمعامل أخير للموازنة بين قيمتين، ثم تحدد الترتيب بناءً على ذلك. لاحظ أنّ <code>‎std::sort‎</code> <a data-ss1617022542="1" href="https://en.wikipedia.org/wiki/Sorting_algorithm#Stability" rel="external nofollow">ليست مستقرة</a>.
</p>

<p>
	يجب أن تفرض دالّة الموازنة <a data-ss1617022542="1" href="https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderings" rel="external nofollow">ترتيبًا صارمًا وضعيفًا</a> على العناصر. وعمومًا فإن عامل الموازنة <code>=&gt;</code> و <code>=&lt;</code> كافيان. وتُستخدم خوارزمية <code>‎std::sort‎</code> لترتيب حاوية ذات مُكرّر وصول عشوائي (random-access iterators):
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9360_6" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;vector&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;algorithm&gt;</span><span class="pln">

std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> </span><span class="typ">MyVector</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">}</span><span class="pln">

</span><span class="com">// &lt; المقارنة الافتراضية لــ</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">sort</span><span class="pun">(</span><span class="typ">MyVector</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> </span><span class="typ">MyVector</span><span class="pun">.</span><span class="pln">end</span><span class="pun">());</span></pre>

<p>
	تتطلّب <code>std::sort</code> أن تكون المكرِّرات عشوائية الوصول، ولا توفّر الحاويَتان <code>std::list</code> و <code>std::forward_list</code> (منذ C++‎ 11) مُكرِّرات وصول عشوائي، لذا لا يمكن استخدامهما مع <code>std::sort</code>. لكن لديهما دالة <code>‎sort‎</code> التابعة، والتي تقدّم خوارزميةَ ترتيبٍ تعمل مع أنواع المكرّرات الخاصّة بها.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9360_8" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;list&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;algorithm&gt;</span><span class="pln">

std</span><span class="pun">::</span><span class="typ">list</span><span class="str">&lt;int&gt;</span><span class="pln"> </span><span class="typ">MyList</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">}</span><span class="pln">

</span><span class="com">// &lt; المقارنة الافتراضية لــ</span><span class="pln">
</span><span class="com">// ترتيب القائمة كاملة </span><span class="pln">
</span><span class="typ">MyList</span><span class="pun">.</span><span class="pln">sort</span><span class="pun">();</span></pre>

<p>
	ترتب الدالة <code>‎sort‎</code> القائمة بأكملها دائمًا، لذا لا يمكنها ترتيب مجموعة فرعية (sub-range) من العناصر، لكن بأي حال بما أن لكلٍّ من القوائم (<code>‎list‎</code>) والقوائم الأمامية <code>‎forward_list‎</code> عمليات ربط سريعة (fast splicing operations)، فتستطيع استخراج العناصر التي تريد ترتيبها من القائمة ثم ترتِّبها، ثم تعيدها حيث كانت على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9360_10" style="">
<span class="kwd">void</span><span class="pln"> sort_sublist</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">list</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> mylist</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">list</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="typ">const_iterator</span><span class="pln"> start</span><span class="pun">,</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">list</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="typ">const_iterator</span><span class="pln"> end</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// استخراج وترتيب المجال الفرعي المحدد</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">list</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> tmp</span><span class="pun">;</span><span class="pln">
    tmp</span><span class="pun">.</span><span class="pln">splice</span><span class="pun">(</span><span class="pln">tmp</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> </span><span class="typ">list</span><span class="pun">,</span><span class="pln"> start</span><span class="pun">,</span><span class="pln"> end</span><span class="pun">);</span><span class="pln">
    tmp</span><span class="pun">.</span><span class="pln">sort</span><span class="pun">();</span><span class="pln">
    </span><span class="com">// إعادة المجال حيث كان</span><span class="pln">
    </span><span class="typ">list</span><span class="pun">.</span><span class="pln">splice</span><span class="pun">(</span><span class="pln">end</span><span class="pun">,</span><span class="pln"> tmp</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	الترتيب باستخدام <code>std::map</code> تصاعديًا وتنازليًا
</h2>

<p>
	يرتّب هذا المثال عناصر قاموس تصاعديًا بحسب المفتاح، وتستطيع استخدام أي نوع بما في ذلك الصنف بدلًا من <code>std::string</code>، انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9360_12" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;utility&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;map&gt;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">map</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">double</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&gt;</span><span class="pln"> sorted_map</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// ترتيب أسماء الكواكب بحسب حجمها</span><span class="pln">
    sorted_map</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">0.3829</span><span class="pun">,</span><span class="pln"> </span><span class="str">"عطارد"</span><span class="pun">));</span><span class="pln">
    sorted_map</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">0.9499</span><span class="pun">,</span><span class="pln"> </span><span class="str">"الزهرة"</span><span class="pun">));</span><span class="pln">
    sorted_map</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="str">"الأرض"</span><span class="pun">));</span><span class="pln">
    sorted_map</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">0.532</span><span class="pun">,</span><span class="pln"> </span><span class="str">"المريخ"</span><span class="pun">));</span><span class="pln">
    sorted_map</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">10.97</span><span class="pun">,</span><span class="pln"> </span><span class="str">"المشتري"</span><span class="pun">));</span><span class="pln">
    sorted_map</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">9.14</span><span class="pun">,</span><span class="pln"> </span><span class="str">"زحل"</span><span class="pun">));</span><span class="pln">
    sorted_map</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">3.981</span><span class="pun">,</span><span class="pln"> </span><span class="str">"أورانوس"</span><span class="pun">));</span><span class="pln">
    sorted_map</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">3.865</span><span class="pun">,</span><span class="pln"> </span><span class="str">"نبتون"</span><span class="pun">));</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> entry</span><span class="pun">:</span><span class="pln"> sorted_map</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> entry</span><span class="pun">.</span><span class="pln">second </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" ("</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> entry</span><span class="pun">.</span><span class="pln">first </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" من قطر الأرض)"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الناتج سيكون:
</p>

<pre class="ipsCode">
(عطارد (0.3829 من قطر الأرض
(المريخ (0.532 من قطر الأرض
(الزهرة (0.9499 من قطر الأرض
(الأرض (1 من قطر الأرض
(نبتون (3.865 من قطر الأرض
(أورانوس (3.981 من قطر الأرض
(زحل (9.14 من قطر الأرض
(المشتري (10.97من قطر الأرض
</pre>

<p>
	إذا كانت هناك مُدخلات ذات مفاتيح متساوية، فاستخدم القاموس المتعدّد <code>‎multimap‎</code> بدلًا من القاموس <code>‎map‎</code> (كما في المثال أدناه).
</p>

<p>
	لترتيب العناصر تنازليا، أعلِن عن القاموس باستخدام عامل موازنة مناسب (<code>‎std::greater&lt;&gt;‎</code>):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9360_14" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;utility&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;map&gt;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">multimap</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">greater </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;&gt;</span><span class="pln"> sorted_map</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// ترتيب أسماء الحيوانات تنازليا بحسب عدد الأرجل</span><span class="pln">
    sorted_map</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="str">"حشرة"</span><span class="pun">));</span><span class="pln">
    sorted_map</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="str">"قطة"</span><span class="pun">));</span><span class="pln">
    sorted_map</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">100</span><span class="pun">,</span><span class="pln"> </span><span class="str">"الحريشية"</span><span class="pun">));</span><span class="pln">
    sorted_map</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="str">"دجاجة"</span><span class="pun">));</span><span class="pln">
    sorted_map</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="str">"سمكة"</span><span class="pun">));</span><span class="pln">
    sorted_map</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="str">"فرس"</span><span class="pun">));</span><span class="pln">
    sorted_map</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="str">"عنكبوت"</span><span class="pun">));</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> entry</span><span class="pun">:</span><span class="pln"> sorted_map</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> entry</span><span class="pun">.</span><span class="pln">second </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" لها "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> entry</span><span class="pun">.</span><span class="pln">first </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" أرجل"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الناتج سيكون:
</p>

<pre class="ipsCode">
الحريشية لها 100 أرجل
العنكبوت لها 8 أرجل
الحشرة لها 6 أرجل
القطة لها 4 أرجل
الفرس لها 4 أرجل
الدجاجة لها 2 أرجل
السمكة لها 0 أرجل
</pre>

<h2>
	ترتيب حاويات التسلسل باستخدام عامل "أصغر من"
</h2>

<p>
	سيرتِّب <code>‎std::sort‎</code> العناصر، إذا لم تُمرَّر أيّ دالة ترتيب، من خلال استدعاء العامل <code>‎operator&lt;‎</code> على أزواج من العناصر، ويجب أن تُعيد نوعًا يمكن تحويله إلى قيمة بوليانية <code>‎bool‎</code>، وتحتوي الأنواع الأساسية (مثل الأعداد الصحيحة، والعشرية، والمؤشرات…) على عوامل موازنة.
</p>

<p>
	نستطيع <a data-ss1617022542="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-22-%D8%A7%D9%84%D8%AA%D8%AD%D9%85%D9%8A%D9%84-%D8%A7%D9%84%D8%B2%D8%A7%D8%A6%D8%AF-overloading-%D8%AA%D8%AD%D9%84%D9%8A%D9%84%D9%87-%D9%88%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D9%87-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D9%81%D9%8A-cpp-r934/" rel="">زيادة تحميل</a> هذا العامل لجعل استدعاء <code>‎sort‎</code> الافتراضي يعمل على الأنواع المُعرّفة من قبل المستخدم. انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9360_16" style="">
<span class="com">// تضمين حاويات التسلسل</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;vector&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;deque&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;list&gt;</span><span class="pln">

</span><span class="com">// تضمن خوارزمية الترتيب</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;algorithm&gt;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="com">// v على القيمة variable منشئ يضبط </span><span class="pln">
        </span><span class="typ">Base</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> v</span><span class="pun">):</span><span class="pln"> variable</span><span class="pun">(</span><span class="pln">v</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span></pre>

<p>
	وهنا استخدم <code>variable</code> لتتيح عامل الترتيب الكامل "أصغر من" أو <code>less</code>، وستمثل <code>this</code> الجانب الأيسر من الموازنة دومًا، نتابع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9360_18" style="">
<span class="pln">        </span><span class="kwd">bool</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">this</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> variable </span><span class="pun">&lt;</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">variable</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="typ">int</span><span class="pln"> variable</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="typ">vector</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">deque </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> deque</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">list</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="typ">list</span><span class="pun">;</span></pre>

<p>
	أنشئ هنا عنصرين لترتيبهما:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9360_20" style="">
<span class="pln">    </span><span class="typ">Base</span><span class="pln"> a</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln">
    </span><span class="typ">Base</span><span class="pln"> b</span><span class="pun">(</span><span class="lit">5</span><span class="pun">);</span></pre>

<p>
	والآن أدرجهما في نهاية الحاوية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9360_22" style="">
<span class="pln">    </span><span class="typ">vector</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">a</span><span class="pun">);</span><span class="pln">
    </span><span class="typ">vector</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">b</span><span class="pun">);</span><span class="pln">

    deque</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">a</span><span class="pun">);</span><span class="pln">
    deque</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">b</span><span class="pun">);</span><span class="pln">

    </span><span class="typ">list</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">a</span><span class="pun">);</span><span class="pln">
    </span><span class="typ">list</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">b</span><span class="pun">);</span></pre>

<p>
	والآن، رتب البيانات باستخدام دالة <code>(operator&lt;(const Base &amp;b</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9360_24" style="">
<span class="pln">    std</span><span class="pun">::</span><span class="pln">sort</span><span class="pun">(</span><span class="typ">vector</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> </span><span class="typ">vector</span><span class="pun">.</span><span class="pln">end</span><span class="pun">());</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">sort</span><span class="pun">(</span><span class="pln">deque</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> deque</span><span class="pun">.</span><span class="pln">end</span><span class="pun">());</span><span class="pln">
    </span><span class="com">// بشكل مختلف List ينبغي ترتيب القائمة</span><span class="pln">
    </span><span class="typ">list</span><span class="pun">.</span><span class="pln">sort</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	ترتيب التسلسلات باستخدام دوال الموازنة
</h2>

<p>
	إليك المثال التوضيحي التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9360_26" style="">
<span class="com">// تضمين التسلسلات</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;vector&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;deque&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;list&gt;</span><span class="pln">

 </span><span class="com">// أدخل خوارزمية الترتيب</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;algorithm&gt;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="com">// v على القيمة variable منشئ يضبط </span><span class="pln">
        </span><span class="typ">Base</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> v</span><span class="pun">):</span><span class="pln"> variable</span><span class="pun">(</span><span class="pln">v</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

    </span><span class="typ">int</span><span class="pln"> variable</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> compare</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> a</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">variable </span><span class="pun">&lt;</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">variable</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="typ">vector</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">deque </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> deque</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">list</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="typ">list</span><span class="pun">;</span></pre>

<p>
	أنشئ عنصرين لترتيبهما:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9360_28" style="">
<span class="pln">    </span><span class="typ">Base</span><span class="pln"> a</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln">
    </span><span class="typ">Base</span><span class="pln"> b</span><span class="pun">(</span><span class="lit">5</span><span class="pun">);</span></pre>

<p>
	أدرج عنصرين في نهاية الحاوية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9360_30" style="">
<span class="pln">    </span><span class="typ">vector</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">a</span><span class="pun">);</span><span class="pln">
    </span><span class="typ">vector</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">b</span><span class="pun">);</span><span class="pln">

    deque</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">a</span><span class="pun">);</span><span class="pln">
    deque</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">b</span><span class="pun">);</span><span class="pln">

    </span><span class="typ">list</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">a</span><span class="pun">);</span><span class="pln">
    </span><span class="typ">list</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">b</span><span class="pun">);</span></pre>

<p>
	رتب البيانات باستخدام دالة الموازنة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9360_32" style="">
<span class="pln">    std</span><span class="pun">::</span><span class="pln">sort</span><span class="pun">(</span><span class="typ">vector</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> </span><span class="typ">vector</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> compare</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">sort</span><span class="pun">(</span><span class="pln">deque</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> deque</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> compare</span><span class="pun">);</span><span class="pln">
    </span><span class="typ">list</span><span class="pun">.</span><span class="pln">sort</span><span class="pun">(</span><span class="pln">compare</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	ترتيب التسلسلات باستخدام تعابير لامدا lambda (‏‏C++‎ 11)
</h2>

<p>
	انظر المثال التوضيحي التالي:
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9360_34" style="">
<span class="com">// تضمين التسلسلات</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;vector&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;deque&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;list&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;array&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;forward_list&gt;</span><span class="pln">

 </span><span class="com">// تضمين خوارزمية الترتيب</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;algorithm&gt;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="com">// v على القيمة variable منشئ يضبط </span><span class="pln">
        </span><span class="typ">Base</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> v</span><span class="pun">):</span><span class="pln"> variable</span><span class="pun">(</span><span class="pln">v</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

    </span><span class="typ">int</span><span class="pln"> variable</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// أنشئ عنصرين لترتيبهما</span><span class="pln">
    </span><span class="typ">Base</span><span class="pln"> a</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln">
    </span><span class="typ">Base</span><span class="pln"> b</span><span class="pun">(</span><span class="lit">5</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// لذا سنستخدم قائمة تهييئ لإدراج العناصر C++11  نحن نستخدم </span><span class="pln">
   std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="typ">Base</span><span class="pun">&gt;</span><span class="pln"> </span><span class="typ">vector</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">};</span><span class="pln">
 std</span><span class="pun">::</span><span class="pln">deque </span><span class="pun">&lt;</span><span class="typ">Base</span><span class="pun">&gt;</span><span class="pln"> deque </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">};</span><span class="pln">
 std</span><span class="pun">::</span><span class="typ">list</span><span class="pln"> </span><span class="pun">&lt;</span><span class="typ">Base</span><span class="pun">&gt;</span><span class="pln"> </span><span class="typ">list</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">};</span><span class="pln">
 std</span><span class="pun">::</span><span class="pln">array </span><span class="pun">&lt;</span><span class="typ">Base</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">&gt;</span><span class="pln"> array </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">};</span><span class="pln">
 std</span><span class="pun">::</span><span class="pln">forward_list</span><span class="pun">&lt;</span><span class="typ">Base</span><span class="pun">&gt;</span><span class="pln"> flist </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">};</span></pre>

<p>
	نستطيع ترتيب البيانات باستخدام تعبير لامدا ضمني (inline).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9360_36" style="">
<span class="pln">    std</span><span class="pun">::</span><span class="pln">sort</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">begin</span><span class="pun">(</span><span class="typ">vector</span><span class="pun">),</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">end</span><span class="pun">(</span><span class="typ">vector</span><span class="pun">),</span><span class="pln">
        </span><span class="pun">[](</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> a</span><span class="pun">,</span><span class="pln">
            </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">variable </span><span class="pun">&lt;</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">variable</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">});</span></pre>

<p>
	كذلك يمكن أن نمرر كائن لامدا كموازن ونعيد استخدامه أكثر من مرة، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9360_38" style="">
<span class="pln">    </span><span class="kwd">auto</span><span class="pln"> compare </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[](</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> a</span><span class="pun">,</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">variable </span><span class="pun">&lt;</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">variable</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">sort</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">begin</span><span class="pun">(</span><span class="pln">deque</span><span class="pun">),</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">end</span><span class="pun">(</span><span class="pln">deque</span><span class="pun">),</span><span class="pln"> compare</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">sort</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">begin</span><span class="pun">(</span><span class="pln">array</span><span class="pun">),</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">end</span><span class="pun">(</span><span class="pln">array</span><span class="pun">),</span><span class="pln"> compare</span><span class="pun">);</span><span class="pln">
    </span><span class="typ">list</span><span class="pun">.</span><span class="pln">sort</span><span class="pun">(</span><span class="pln">compare</span><span class="pun">);</span><span class="pln">
    flist</span><span class="pun">.</span><span class="pln">sort</span><span class="pun">(</span><span class="pln">compare</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	ترتيب المصفوفات المبنية مسبقًا
</h2>

<p>
	ترتّب خوارزمية <code>‎sort‎</code> التسلسلات المُعرّفة بواسطة المُكرِّرات، وهذا كاف لترتيب مصفوفة ما مبنية مسبًا (تُعرَف أيضًا باسم مصفوفات من نمط C).
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9360_40" style="">
<span class="typ">int</span><span class="pln"> arr1</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">36</span><span class="pun">,</span><span class="pln"> </span><span class="lit">24</span><span class="pun">,</span><span class="pln"> </span><span class="lit">42</span><span class="pun">,</span><span class="pln"> </span><span class="lit">60</span><span class="pun">,</span><span class="pln"> </span><span class="lit">59</span><span class="pun">};</span><span class="pln"> 

</span><span class="com">// ترتيب الأعداد تصاعديا</span><span class="pln">
sort</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">begin</span><span class="pun">(</span><span class="pln">arr1</span><span class="pun">),</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">end</span><span class="pun">(</span><span class="pln">arr1</span><span class="pun">));</span><span class="pln">

</span><span class="com">// ترتيب الأعداد تنازليا</span><span class="pln">
sort</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">begin</span><span class="pun">(</span><span class="pln">arr1</span><span class="pun">),</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">end</span><span class="pun">(</span><span class="pln">arr1</span><span class="pun">),</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">greater </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">());</span></pre>

<p>
	قبل الإصدار C++‎ 11، كان من اللازم حساب نهاية المصفوفة باستخدام حجمها:
</p>

<p>
	<strong>الإصدار &lt; C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9360_42" style="">
<span class="com">// استخدام قيمة مباشرة</span><span class="pln">
sort</span><span class="pun">(</span><span class="pln">arr1</span><span class="pun">,</span><span class="pln"> arr1 </span><span class="pun">+</span><span class="pln"> </span><span class="lit">5</span><span class="pun">);</span><span class="pln">

</span><span class="com">// استخدام تعبير كحل بديل</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">size_t</span><span class="pln"> arr1_size </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">arr1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> arr1</span><span class="pun">);</span><span class="pln">
sort</span><span class="pun">(</span><span class="pln">arr1</span><span class="pun">,</span><span class="pln"> arr1 </span><span class="pun">+</span><span class="pln"> arr1_size</span><span class="pun">);</span></pre>

<h2>
	ترتيب تسلسل باستخدام ترتيب مخصّص
</h2>

<p>
	إن كانت للقيم الموجودة في الحاوية عوامل مُحمّلة تحميلًا زائدًا، فنستخدم <code>‎std::sort‎</code> مع كائن دالّي مُخصّص لترتيب عناصر الحاوية تصاعديًا أو تنازليًا:
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9360_44" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;vector&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;algorithm&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;functional&gt;</span><span class="pln">

std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> v </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">5</span><span class="pun">,</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">,</span><span class="lit">4</span><span class="pun">,</span><span class="lit">3</span><span class="pun">};</span><span class="pln"> 

</span><span class="com">// (1,2,3,4,5) الترتيب التصاعدي</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">sort</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">less </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">());</span><span class="pln">

</span><span class="com">// أو</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">sort</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">());</span><span class="pln">

</span><span class="com">// (5,4,3,2,1) الترتيب التنازلي</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">sort</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">greater </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">());</span><span class="pln">

</span><span class="com">// أو</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">sort</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">rbegin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">rend</span><span class="pun">());</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 14</strong>
</p>

<p>
	في الإصدار C++‎ 14، ليس علينا تمرير وسيط القالب لدوالّ الموازنة، إذ يمكن استنتاج ذلك استنادًا إلى ما تم تمريره:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9360_46" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">sort</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">less</span><span class="pun">&lt;&gt;());</span><span class="pln"> </span><span class="com">// ترتيب تصاعدي</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">sort</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">greater</span><span class="pun">&lt;&gt;());</span><span class="pln"> </span><span class="com">// ترتيب تنازلي</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617022542="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 67: Sorting من كتاب <a data-ss1617022542="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">955</guid><pubDate>Sat, 15 Aug 2020 18:03:00 +0000</pubDate></item><item><title>&#x62A;&#x648;&#x644;&#x64A;&#x62F; &#x627;&#x644;&#x623;&#x639;&#x62F;&#x627;&#x62F; &#x627;&#x644;&#x639;&#x634;&#x648;&#x627;&#x626;&#x64A;&#x629; &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%AA%D9%88%D9%84%D9%8A%D8%AF-%D8%A7%D9%84%D8%A3%D8%B9%D8%AF%D8%A7%D8%AF-%D8%A7%D9%84%D8%B9%D8%B4%D9%88%D8%A7%D8%A6%D9%8A%D8%A9-%D9%81%D9%8A-cpp-r954/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_08/33.png.0e8dd4002952fd8e333abb463cc8f5cb.png" /></p>

<h2>
	مولد قيم عشوائية حقيقيّة
</h2>

<p>
	لإنشاء قيم عشوائية حقّا (generate true random) يمكن استخدامها في التشفير، يجب استخدام <code>‎std::random_device‎</code> كمُولِّد.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4210_6" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;random&gt;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">random_device crypto_random_generator</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">uniform_int_distribution </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> int_distribution</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pun">);</span><span class="pln">

 </span><span class="typ">int</span><span class="pln"> actual_distribution</span><span class="pun">[</span><span class="lit">10</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">};</span><span class="pln"> 

    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10000</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> result </span><span class="pun">=</span><span class="pln"> int_distribution</span><span class="pun">(</span><span class="pln">crypto_random_generator</span><span class="pun">);</span><span class="pln">
        actual_distribution</span><span class="pun">[</span><span class="pln">result</span><span class="pun">]++;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> actual_distribution</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" "</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تُستخدم <code>std::random_device</code> بنفس طريقة استخدام مولّد القيم العشوائية الزائفة (pseudo random value).
</p>

<p>
	ورغم ذلك <strong>فيمكن تنفيذ <code>‎std::random_device‎</code> انطلاقًا من محرّك أعداد عشوائية زائفة تُحدد وفق التنفيذ</strong> في حال لم يتوفّر مصدر غير حتمي (non-deterministic) مثل جهاز خاص بتوليد القيم العشوائية لاستخدامه في التنفيذ.
</p>

<p>
	يمكن الكشف عن مثل هذه التنفيذات من خلال الدالة التابعة <code>‎entropy‎</code> (التي تعيد 0 في حال كان المولد حتميًّا تمامًا)، لكنّ العديد من المكتبات الشائعة (مثل libstdc++‎ و LLVM's libc++‎) تعيد دائمًا القيمة 0، حتى عند استخدام مولّدات عشوائية خارجية عالية الجودة .
</p>

<h2>
	توليد عدد عشوائي زائف
</h2>

<p>
	تنشئ مولّدات الأعداد شبه العشوائية قيمًا يمكن تخمينها استنادًا إلى القيم التي تم توليدها سابقًا، هذا يعني أنها حتمية. ولا تستخدم مولّدات الأعداد شبه العشوائية في الحالات التي تستلزم أعدادًا عشوائية حقًّا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4210_8" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;random&gt;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">default_random_engine pseudo_random_generator</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">uniform_int_distribution </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> int_distribution</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pun">);</span><span class="pln">

    </span><span class="typ">int</span><span class="pln"> actual_distribution</span><span class="pun">[</span><span class="lit">10</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">};</span><span class="pln"> 

    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10000</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> result </span><span class="pun">=</span><span class="pln"> int_distribution</span><span class="pun">(</span><span class="pln">pseudo_random_generator</span><span class="pun">);</span><span class="pln">
        actual_distribution</span><span class="pun">[</span><span class="pln">result</span><span class="pun">]++;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">9</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> actual_distribution</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" "</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تنشئ هذه الشيفرة مولّدَ أعدادٍ عشوائية زائفة، وتوزيعًا يولّد أعدادًا صحيحة في نطاق [0،9] باحتمال متساوي، ويحسب المولّد بعد ذلك عدد مرّات إنشاء كل نتيجة.
</p>

<p>
	يحدّد معامل القالب <code>‎<a data-ss1617022540="1" href="https://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution" rel="external nofollow">std::uniform_int_distribution&lt;T&gt;‎</a></code> نوع العدد الصحيح الذي يجب إنشاؤه. استخدم <code><a data-ss1617022540="1" href="https://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution" rel="external nofollow">‎std::uniform_real_distribution&lt;T&gt;‎</a></code> لتوليد الأعداد العشرية (ﬂoats) والأعداد العشرية المزدوجة (doubles).
</p>

<h2>
	استخدام المولد مع عدة توزيعات
</h2>

<p>
	من الممكن استخدام مولّد الأعداد العشوائية مع عدة توزيعات، ويجب ذلك حقيقة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4210_12" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;random&gt;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">default_random_engine pseudo_random_generator</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">uniform_int_distribution </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> int_distribution</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">uniform_real_distribution </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">float</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> float_distribution</span><span class="pun">(</span><span class="lit">0.0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1.0</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">discrete_distribution rigged_dice</span><span class="pun">({</span><span class="lit">1</span><span class="pun">,</span><span class="lit">1</span><span class="pun">,</span><span class="lit">1</span><span class="pun">,</span><span class="lit">1</span><span class="pun">,</span><span class="lit">1</span><span class="pun">,</span><span class="lit">100</span><span class="pun">});</span><span class="pln"> 

    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> int_distribution</span><span class="pun">(</span><span class="pln">pseudo_random_generator</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> float_distribution</span><span class="pun">(</span><span class="pln">pseudo_random_generator</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">rigged_dice</span><span class="pun">(</span><span class="pln">pseudo_random_generator</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	عرّفنا في هذا المثال مولِّدًا واحدًا فقط، ثمّ استخدمناه لإنشاء أعداد عشوائية في ثلاثة توزيعات مختلفة، وسيولّد التوزيع <code>‎rigged_dice‎</code> قيمة بين 0 و 5، لكن سيولّد في الأغلبية الساحقة من الحالات <code>‎5‎</code>، لأنّ احتمال إنشاء <code>‎5‎</code> يساوي <code>‎100 / 105‎</code>.
</p>

<p>
	هذا الدرس جزء من <a data-ss1617022540="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 65: Random number generation من كتاب <a data-ss1617022540="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">954</guid><pubDate>Wed, 12 Aug 2020 18:00:00 +0000</pubDate></item><item><title>&#x62E;&#x648;&#x627;&#x631;&#x632;&#x645;&#x64A;&#x627;&#x62A; &#x627;&#x644;&#x645;&#x643;&#x62A;&#x628;&#x629; &#x627;&#x644;&#x642;&#x64A;&#x627;&#x633;&#x64A;&#x629; std &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%AE%D9%88%D8%A7%D8%B1%D8%B2%D9%85%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D9%83%D8%AA%D8%A8%D8%A9-%D8%A7%D9%84%D9%82%D9%8A%D8%A7%D8%B3%D9%8A%D8%A9-std-%D9%81%D9%8A-cpp-r953/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_08/32.png.92a98d479b6a5b817af705f939d20c55.png" /></p>

<h2>
	<code>std::next_permutation</code>
</h2>

<p>
	المثال التالي يبدل تسلسل المجال [ﬁrst, last] ويحوّله إلى التبديل التالي الأعلى في الترتيب المعجمي (lexicographically higher permutation)، ويمكن تخصيص قاعدة التبديل عبر <code>‎cmpFun‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_6" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Iterator</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
  </span><span class="kwd">bool</span><span class="pln"> next_permutation</span><span class="pun">(</span><span class="typ">Iterator</span><span class="pln"> first</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Iterator</span><span class="pln"> last</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Iterator</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Compare</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
  </span><span class="kwd">bool</span><span class="pln"> next_permutation</span><span class="pun">(</span><span class="typ">Iterator</span><span class="pln"> first</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Iterator</span><span class="pln"> last</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Compare</span><span class="pln"> cmpFun</span><span class="pun">);</span></pre>

<h3>
	المعاملات
</h3>

<ul>
<li>
		<code>‎first‎</code> - بداية المجال المُراد تبديله (مُضمّن)
	</li>
	<li>
		<code>‎last‎</code> - نهاية المجال المراد تبديله (غير مُضمّن)
	</li>
</ul>
<h3>
	القيمة المعادة
</h3>

<p>
	تعيد <code>true</code> إن كان التبديل موجودًا، وخلاف ذلك، يُحوّل المجال إلى أصغر تبديل معجمية (lexicographically smallest permutation)، ثم تُعاد القيمة <code>false</code>.
</p>

<h3>
	التعقيد Complexity
</h3>

<p>
	التعقيد يساوي O(n)‎، حيث تمثّل n المسافة من <code>‎first‎</code> إلى <code>‎last‎</code>. إليك المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_8" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v </span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">};</span><span class="pln"> 
</span><span class="kwd">do</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">size</span><span class="pun">();</span><span class="pln"> i </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> v</span><span class="pun">[</span><span class="pln">i</span><span class="pun">];</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">next_permutation</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">()));</span></pre>

<p>
	هذا يطبع جميع تقليبات المجال 1،2،3 وفق ترتيب معجمي تصاعدي.
</p>

<p>
	الخرج:
</p>

<pre class="ipsCode">
123
132
213
231
312
321
</pre>

<h2>
	<code>std::for_each</code>
</h2>

<p>
	في الشيفرة أدناه، نطبّق الدالّة <code>‎f‎</code> على نتيجة تحصيل كلّ مُكرّر في المجال <code>‎[first, last)‎</code> بدءًا من <code>‎first‎</code> وحتى <code>‎last - 1‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_10" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">InputIterator</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Function</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
  </span><span class="typ">Function</span><span class="pln"> for_each</span><span class="pun">(</span><span class="typ">InputIterator</span><span class="pln"> first</span><span class="pun">,</span><span class="pln"> </span><span class="typ">InputIterator</span><span class="pln"> last</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Function</span><span class="pln"> f</span><span class="pun">);</span></pre>

<h3>
	المعاملات
</h3>

<ul>
<li>
		<code>‎first, last‎</code> - المجال الذي ستُطبّق <code>‎f‎</code> عليه.
	</li>
	<li>
		<code>‎f‎</code> - كائن قابل للاستدعاء يُطبّق على نتيجة تحصيل كل مكرّر في المجال [<code>‎first, last‎</code>).
	</li>
</ul>
<h3>
	القيمة المُعادة
</h3>

<p>
	تعاد <code>‎f‎</code> إن كان الإصدار أقدم من C++‎ 11، وإلّا فستُعاد <code>std::move(f)‎</code>.
</p>

<h3>
	التعقيد
</h3>

<p>
	تُطبّق <code>‎f‎</code> عدد <code>‎last - first‎</code> مرّة.
</p>

<p>
	<strong>مثال</strong>
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_12" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v </span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">16</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">for_each</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> </span><span class="pun">[](</span><span class="typ">int</span><span class="pln"> elem</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> elem </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" "</span><span class="pun">;</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	تطبيق الدالّة المُعطاة على كل عنصر من المتجه <code>‎v‎</code> يؤدي إلى طباعة هذا العنصر في مجرى الخرج <code>‎stdout‎</code>.
</p>

<h2>
	<code>std::accumulate</code>
</h2>

<p>
	هذه الخوارزمية مُعرّّفة في الترويسة <numeric></numeric></p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_14" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">InputIterator</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
  T accumulate</span><span class="pun">(</span><span class="typ">InputIterator</span><span class="pln"> first</span><span class="pun">,</span><span class="pln"> </span><span class="typ">InputIterator</span><span class="pln"> last</span><span class="pun">,</span><span class="pln"> T init</span><span class="pun">);</span><span class="pln"> </span><span class="com">// (1)</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">InputIterator</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">BinaryOperation</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
  T accumulate</span><span class="pun">(</span><span class="typ">InputIterator</span><span class="pln"> first</span><span class="pun">,</span><span class="pln"> </span><span class="typ">InputIterator</span><span class="pln"> last</span><span class="pun">,</span><span class="pln"> T init</span><span class="pun">,</span><span class="pln"> </span><span class="typ">BinaryOperation</span><span class="pln"> f</span><span class="pun">);</span><span class="pln"> </span><span class="com">// (2)</span></pre>

<p>
	تُجرى <a data-ss1617022534="1" href="https://en.cppreference.com/w/cpp/algorithm/accumulate" rel="external nofollow">std::accumulate</a> عملية الطي (fold operation) باستخدام الدالّة <code>‎f‎</code> على المجال <code>‎[first, last)‎</code> بدءا من <code>‎init‎</code> كقيمة تراكمية (accumulator value)، وهذا يكافئ:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_16" style="">
<span class="pln">T acc </span><span class="pun">=</span><span class="pln"> init</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> first</span><span class="pun">;</span><span class="pln"> first </span><span class="pun">!=</span><span class="pln"> last</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">it</span><span class="pun">)</span><span class="pln">
  acc </span><span class="pun">=</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">acc</span><span class="pun">,</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> it</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> acc</span><span class="pun">;</span></pre>

<p>
	في الإصدار (1)، يُستخدم <code>‎operator+‎</code> بدلًا من <code>‎f‎</code>، لذا فإنّ مراكمة قيمِ حاويةٍ يعادل مجموع عناصر تلك الحاوية.
</p>

<h3>
	المعاملات
</h3>

<ul>
<li>
		<code>‎first, last‎</code> - المجال الذي ستُطبّق <code>‎f‎</code> عليه.
	</li>
	<li>
		<code>‎init‎</code> - القيمة الأولية للتراكم.
	</li>
	<li>
		<code>‎f‎</code> - دالّة الطي الثنائية (binary folding function).
	</li>
</ul>
<h3>
	القيمة المُعادة
</h3>

<p>
	القيمة المتراكمة الناتجة عن التطبيق المتتابع للدالّة <code>‎f‎</code>.
</p>

<h3>
	التعقيد
</h3>

<p>
	التعقيد يساوي O(n × k)‎، و n هنا يمثّل المسافة من <code>‎first‎</code> إلى <code>‎last‎</code>، فيما تمثّل O(k)‎ تعقيد الدالّة <code>‎f‎</code>. انظر المثال البسيط التالي عن مُراكمة الجَمْع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_18" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v </span><span class="pun">{</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> sum </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">accumulate</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> sum </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></pre>

<p>
	الناتج سيكون:
</p>

<pre class="ipsCode">
10
</pre>

<p>
	تحويل الأرقام (digits) إلى عدد (number):
</p>

<p>
	<strong>الإصدار&lt;C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_20" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Converter</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">()(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> d</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      </span><span class="kwd">return</span><span class="pln"> a </span><span class="pun">*</span><span class="pln"> </span><span class="lit">10</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> d</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	ثمّ:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_22" style="">
<span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> ds</span><span class="pun">[</span><span class="lit">3</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> n </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">accumulate</span><span class="pun">(</span><span class="pln">ds</span><span class="pun">,</span><span class="pln"> ds </span><span class="pun">+</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Converter</span><span class="pun">());</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> n </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_24" style="">
<span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> ds </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> n </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">accumulate</span><span class="pun">(</span><span class="pln">ds</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> ds</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln">
 </span><span class="lit">0</span><span class="pun">,</span><span class="pln">
</span><span class="pun">[](</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> d</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> a </span><span class="pun">*</span><span class="pln"> </span><span class="lit">10</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> d</span><span class="pun">;</span><span class="pln"> </span><span class="pun">});</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> n </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></pre>

<p>
	الناتج سيكون:
</p>

<pre class="ipsCode" id="ips_uid_751_26">
123
</pre>

<h2>
	<code>std::ﬁnd</code>
</h2>

<p>
	تساعد <code>std::ﬁnd</code> على العثور على أوّل ظهور لعنصر <code>val</code> داخل مجال ‎[ﬁrst, last)‎‎‎.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_28" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">InputIterator</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
  </span><span class="typ">InputIterator</span><span class="pln"> find </span><span class="pun">(</span><span class="typ">InputIterator</span><span class="pln"> first</span><span class="pun">,</span><span class="pln"> </span><span class="typ">InputIterator</span><span class="pln"> last</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> T</span><span class="pun">&amp;</span><span class="pln"> val</span><span class="pun">);</span></pre>

<h3>
	المعاملات
</h3>

<ul>
<li>
		<code>‎first‎</code> : يمثل <a data-ss1617022534="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-8-%D8%A7%D9%84%D9%85%D9%83%D8%B1%D8%A7%D8%B1%D8%A7%D8%AA-iterators-%D9%81%D9%8A-cpp-r892/" rel="">مُكرّرًا</a> يشير إلى بداية المجال.
	</li>
	<li>
		<code>‎last‎</code> يمثل مُكرّرًا يشير إلى نهاية المجال.
	</li>
	<li>
		<code>‎val‎</code> يمثل القيمة المبحوث عنها داخل المجال.
	</li>
</ul>
<h3>
	القيمة المعادة
</h3>

<p>
	يُعاد مكرِّر يشير إلى أوّل عنصر في المجال يساوي (==) <code>val</code>، أما إن لم يكن هناك عنصر يحقّق ذلك، فسيُعاد مكرّر يشير إلى <code>last</code>. انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_30" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;vector&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;algorithm&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> std</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> argc</span><span class="pun">,</span><span class="pln">
  </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> argv</span><span class="pun">[])</span><span class="pln"> </span><span class="pun">{</span></pre>

<p>
	سننشئ متجهًا هنا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_32" style="">
<span class="pln"> </span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> intVec </span><span class="pun">{</span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">,</span><span class="pln"> </span><span class="lit">30</span><span class="pun">,</span><span class="pln"> </span><span class="lit">55</span><span class="pun">,</span><span class="lit">100</span><span class="pun">,</span><span class="pln"> </span><span class="lit">45</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pun">,</span><span class="pln"> </span><span class="lit">43</span><span class="pun">,</span><span class="pln"> </span><span class="lit">48</span><span class="pun">};</span></pre>

<p>
	ثم نعرِّف المكرِّرات:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_34" style="">
<span class="pln">  </span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="typ">iterator</span><span class="pln"> itr_9</span><span class="pun">;</span><span class="pln">
  </span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="typ">iterator</span><span class="pln"> itr_43</span><span class="pun">;</span><span class="pln">
  </span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="typ">iterator</span><span class="pln"> itr_50</span><span class="pun">;</span></pre>

<p>
	والآن نستدعي <code>find</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_36" style="">
<span class="pln">  itr_9 </span><span class="pun">=</span><span class="pln"> find</span><span class="pun">(</span><span class="pln">intVec</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> intVec</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> </span><span class="lit">9</span><span class="pun">);</span><span class="pln"> </span><span class="com">//occurs twice</span><span class="pln">
  itr_43 </span><span class="pun">=</span><span class="pln"> find</span><span class="pun">(</span><span class="pln">intVec</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> intVec</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> </span><span class="lit">43</span><span class="pun">);</span><span class="pln"> </span><span class="com">//occurs once</span><span class="pln">

  </span><span class="com">// قيمة غير موجودة في المتجهة</span><span class="pln">
  itr_50 </span><span class="pun">=</span><span class="pln"> find</span><span class="pun">(</span><span class="pln">intVec</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> intVec</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> </span><span class="lit">50</span><span class="pun">);</span><span class="pln"> </span><span class="com">//does not occur</span><span class="pln">
  cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"first occurrence of: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> itr_9 </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
  cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"only occurrence of: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> itr_43 </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span></pre>

<p>
	نستطيع إثبات أن <code>itr_9</code> تشير إلى الظهور الأول لـ 9 عبر فحص القيمة التي تلي 9، والتي يجب أن تكون 10 وليس 43، نتابع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_38" style="">
<span class="pln">  cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"element after first 9: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">(</span><span class="pln">itr_9 </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> ends</span><span class="pun">;</span></pre>

<p>
	وسنلقي نظرة على العنصر الموجود قبل النهاية لتجنب تحصيل <code>()intVec.end</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_40" style="">
<span class="pln">  cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"last element: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">(</span><span class="pln">itr_50 </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يكون ناتج ذلك كله:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_42" style="">
<span class="pln">first occurrence of</span><span class="pun">:</span><span class="pln"> </span><span class="lit">9</span><span class="pln">
only occurrence of</span><span class="pun">:</span><span class="pln"> </span><span class="lit">43</span><span class="pln">
element after first </span><span class="lit">9</span><span class="pun">:</span><span class="pln"> </span><span class="lit">10</span><span class="pln">
last element</span><span class="pun">:</span><span class="pln"> </span><span class="lit">48</span></pre>

<h2>
	<code>std::min_element</code>
</h2>

<p>
	تُستخدم <code>std::min_element</code> لإيجاد أصغر عنصر في مجال معيّن.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_44" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">ForwardIterator</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="typ">ForwardIterator</span><span class="pln"> min_element</span><span class="pun">(</span><span class="typ">ForwardIterator</span><span class="pln"> first</span><span class="pun">,</span><span class="pln"> </span><span class="typ">ForwardIterator</span><span class="pln"> last</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">ForwardIterator</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Compare</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="typ">ForwardIterator</span><span class="pln"> min_element</span><span class="pun">(</span><span class="typ">ForwardIterator</span><span class="pln"> first</span><span class="pun">,</span><span class="pln"> </span><span class="typ">ForwardIterator</span><span class="pln"> last</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Compare</span><span class="pln"> comp</span><span class="pun">);</span></pre>

<h3>
	المعاملات
</h3>

<ul>
<li>
		<code>‎first‎</code> - مكرّر يشير إلى بداية المجال
	</li>
	<li>
		<code>‎last‎</code> - مكرّر يشير إلى نهاية المجال
	</li>
	<li>
		<code>‎comp‎</code> - مؤشّر دالّة أو كائن دالّة يأخذ وسيطين ويعيد إما <code>true</code> أو <code>false</code> موضحًا إذا كان الوسيط الأول أصغر من الوسيط الثاني. يُشتَرَط ألًا تعدّل هذه الدالّة المُدخلاتِ.
	</li>
</ul>
<h3>
	القيمة المعادة
</h3>

<p>
	يُعاد مكرّر إلى أصغر عنصر في المجال.
</p>

<h3>
	التعقيد
</h3>

<p>
	التعقيد يساوي O(1)‎ - n‎، حيث يمثل n عدد العناصر المُقارنَة. انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_46" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;algorithm&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;vector&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;utility&gt;</span><span class="pln">  </span><span class="com">// make_pair لاستخدام</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> std</span><span class="pun">;</span><span class="pln">

</span><span class="com">// دالّة تقارن زوجين</span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> pairLessThanFunction</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> pair </span><span class="pun">&lt;</span><span class="pln"> string</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> p1</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> pair </span><span class="pun">&lt;</span><span class="pln"> string</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> p2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> p1</span><span class="pun">.</span><span class="pln">second </span><span class="pun">&lt;</span><span class="pln"> p2</span><span class="pun">.</span><span class="pln">second</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> argc</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> argv</span><span class="pun">[])</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

   </span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> intVec </span><span class="pun">{</span><span class="lit">30</span><span class="pun">,</span><span class="lit">200</span><span class="pun">,</span><span class="lit">167</span><span class="pun">,</span><span class="lit">56</span><span class="pun">,</span><span class="lit">75</span><span class="pun">,</span><span class="lit">94</span><span class="pun">,</span><span class="lit">10</span><span class="pun">,</span><span class="lit">73</span><span class="pun">,</span><span class="lit">52</span><span class="pun">,</span><span class="lit">6</span><span class="pun">,</span><span class="lit">39</span><span class="pun">,</span><span class="lit">43</span><span class="pun">};</span><span class="pln">

   </span><span class="typ">vector</span><span class="pun">&gt;</span><span class="pln"> pairVector </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">make_pair</span><span class="pun">(</span><span class="str">"y"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">25</span><span class="pun">),</span><span class="pln"> make_pair</span><span class="pun">(</span><span class="str">"b"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">),</span><span class="pln"> make_pair</span><span class="pun">(</span><span class="str">"z"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">26</span><span class="pun">),</span><span class="pln"> make_pair</span><span class="pun">(</span><span class="str">"e"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">)</span><span class="pln"> </span><span class="pun">};</span><span class="pln">

    </span><span class="com">// &lt; العامل الافتراضي هو</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> minInt </span><span class="pun">=</span><span class="pln"> min_element</span><span class="pun">(</span><span class="pln">intVec</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> intVec</span><span class="pun">.</span><span class="pln">end</span><span class="pun">());</span><span class="pln">

    </span><span class="com">// pairLessThanFunction استخدام</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> minPairFunction </span><span class="pun">=</span><span class="pln"> min_element</span><span class="pun">(</span><span class="pln">pairVector</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> pairVector</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> pairLessThanFunction</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// intVector اطبع أصغر قيمة في</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"min int from default: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> minInt </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// pairVector اطبع أصغر قيمة في</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"min pair from PairLessThanFunction: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> minPairFunction</span><span class="pun">).</span><span class="pln">second </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الناتج سيكون:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_48" style="">
<span class="pln">min </span><span class="typ">int</span><span class="pln"> from </span><span class="kwd">default</span><span class="pun">:</span><span class="pln"> </span><span class="lit">6</span><span class="pln">
min pair from </span><span class="typ">PairLessThanFunction</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2</span></pre>

<h2>
	<code>std::ﬁnd_if</code>
</h2>

<p>
	تُستخدم <code>std::ﬁnd_if</code> لإيجاد أوّل عنصر في المجال يحقّق دالّة شرطية <code>‎pred‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_50" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">InputIterator</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">UnaryPredicate</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="typ">InputIterator</span><span class="pln"> find_if</span><span class="pun">(</span><span class="typ">InputIterator</span><span class="pln"> first</span><span class="pun">,</span><span class="pln"> </span><span class="typ">InputIterator</span><span class="pln"> last</span><span class="pun">,</span><span class="pln"> </span><span class="typ">UnaryPredicate</span><span class="pln"> pred</span><span class="pun">);</span></pre>

<h3>
	المُعاملات
</h3>

<ul>
<li>
		<code>‎first‎</code> =&gt; مكرّر يشير إلى بداية المجال
	</li>
	<li>
		<code>‎last‎</code> =&gt; مكرّر يشير إلى نهاية المجال
	</li>
	<li>
		<code>‎pred‎</code> =&gt; دالّة شرطية - predicate - (تعيد إمّا true أو false)
	</li>
</ul>
<h3>
	القيمة المعادة
</h3>

<p>
	يُعاد مكرّر يشير إلى أول عنصر في المجال يحقّق الدالّة الشرطية، وسيُعاد مكرّر إلى <code>last</code> في حال لم يكن هناك أيّ عنصر يحقّق ذلك. انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_52" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;vector&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;algorithm&gt;</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> std</span><span class="pun">;</span><span class="pln">
</span><span class="com">/*
عرِّف بعض الدوالّ الشرطية
*/</span><span class="pln">
</span><span class="com">// يساوي 10 x إن كان true إعادة</span><span class="pln">

</span><span class="kwd">bool</span><span class="pln"> multOf10</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> x </span><span class="pun">%</span><span class="pln"> </span><span class="lit">10</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// إن كان العنصر أكبر من القيمة الممرّرة true إعادة </span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Greater</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> _than</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Greater</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> th</span><span class="pun">):</span><span class="pln"> _than</span><span class="pun">(</span><span class="pln">th</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

        </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">bool</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">()(</span><span class="typ">int</span><span class="pln"> data</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> data </span><span class="pun">&gt;</span><span class="pln"> _than</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

 </span><span class="typ">vector</span><span class="pln"> myvec </span><span class="pun">{</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">,</span><span class="pln"> </span><span class="lit">56</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pun">,</span><span class="pln"> </span><span class="lit">48</span><span class="pun">,</span><span class="pln"> </span><span class="lit">89</span><span class="pun">,</span><span class="pln"> </span><span class="lit">850</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pun">,</span><span class="pln"> </span><span class="lit">456</span><span class="pun">};</span><span class="pln"> 

    </span><span class="com">// lambda مع دالّة </span><span class="pln">
    </span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="typ">iterator</span><span class="pln"> gt10 </span><span class="pun">=</span><span class="pln"> find_if</span><span class="pun">(</span><span class="pln">myvec</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> myvec</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> </span><span class="pun">[](</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> x </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">});</span><span class="pln"> </span><span class="com">// &gt;=</span><span class="pln">

    </span><span class="com">// مع مؤشّر دالّة</span><span class="pln">
    </span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="typ">iterator</span><span class="pln"> pow10 </span><span class="pun">=</span><span class="pln"> find_if</span><span class="pun">(</span><span class="pln">myvec</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> myvec</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> multOf10</span><span class="pun">);</span><span class="pln">

     </span><span class="com">// مع كائن دالّي</span><span class="pln">
    </span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="typ">iterator</span><span class="pln"> gt5 </span><span class="pun">=</span><span class="pln"> find_if</span><span class="pun">(</span><span class="pln">myvec</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> myvec</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> </span><span class="typ">Greater</span><span class="pun">(</span><span class="lit">5</span><span class="pun">));</span><span class="pln">

    </span><span class="com">// غير موجود</span><span class="pln">
    </span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="typ">iterator</span><span class="pln"> nf </span><span class="pun">=</span><span class="pln"> find_if</span><span class="pun">(</span><span class="pln">myvec</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> myvec</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> </span><span class="typ">Greater</span><span class="pun">(</span><span class="lit">1000</span><span class="pun">));</span><span class="pln"> </span><span class="com">// nf points to</span><span class="pln">
    myvec</span><span class="pun">.</span><span class="pln">end</span><span class="pun">();</span><span class="pln">

 </span><span class="com">// myvec.end() التحقّق مما إذا كان المؤشّر يشير إلى</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">nf </span><span class="pun">!=</span><span class="pln"> myvec</span><span class="pun">.</span><span class="pln">end</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"nf points to: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> nf </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"item not found"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"First item &gt;   10: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> gt10 </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"First Item n * 10: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> pow10 </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"First Item &gt;    5: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> gt5 </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الناتج سيكون:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_54" style="">
<span class="pln">item not found
</span><span class="typ">First</span><span class="pln"> item </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">:</span><span class="pln"> </span><span class="lit">56</span><span class="pln">
</span><span class="typ">First</span><span class="pln"> </span><span class="typ">Item</span><span class="pln"> n </span><span class="pun">*</span><span class="pln"> </span><span class="lit">10</span><span class="pun">:</span><span class="pln"> </span><span class="lit">10</span><span class="pln">
</span><span class="typ">First</span><span class="pln"> </span><span class="typ">Item</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">5</span><span class="pun">:</span><span class="pln"> </span><span class="lit">6</span></pre>

<h2>
	استخدام <code>std::nth_element</code> لإيجاد الوسيط
</h2>

<p>
	تأخذ خوارزمية <a data-ss1617022534="1" href="https://en.cppreference.com/w/cpp/algorithm/nth_element" rel="external nofollow">‎std::nth_element‎</a> ثلاثة مُكرِّرات: مكرّر يشير إلى البداية، وآخر يشير إلى الموضع n، وآخر يشير إلى النهاية. وبمجرد عودة الدالّة، سيكون العنصر رقم n (في الترتيب وليس في الموضع) هو أصغر n عنصر. تحتوي الدالّة على تحميلات زائدة أكثر تفصيلًا، على سبيل المثال، بعضها تأخذ كائنات دالّية للموازنة.
</p>

<p>
	ملاحظة: هذه الدالّة فعّالة للغاية - إذ أنّ تعقيدها خطّي.
</p>

<p>
	في المثال التالي، سنُعرّف <a data-ss1617022534="1" href="https://ar.wikipedia.org/wiki/%D9%88%D8%B3%D9%8A%D8%B7_(%D8%A5%D8%AD%D8%B5%D8%A7%D8%A1)" rel="external nofollow">الوسيط</a> median، وهو القيمة التي تفصل النصف الأعلى من التسلسل عن النصف الأصغر بحيث يتساوى على طرفيه عدد القيم بعد ترتيبها تصاعديًا، أي أنه العنصر الأوسط في الترتيب. للتّبسيط، سنُعرّف وسيط تسلسل مكوّن من n عنصر على أنّه العنصر الموجود في الموضع ⌈ n / 2 ⌉ حسب الترتيب. مثلًا، سيكون وسيط تسلسل طوله 5 هو العنصر الأصغر الثالث، وكذلك وسيط تسلسل بطول 6 عناصر.
</p>

<p>
	لاستخدام هذه الدالّة لإيجاد الوسيط، يمكننا استخدام ما يلي، لنبدأ بــ:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_56" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> v</span><span class="pun">{</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">};</span><span class="pln">  

std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="typ">iterator</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">();</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="typ">iterator</span><span class="pln"> e </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">();</span><span class="pln">

std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="typ">iterator</span><span class="pln"> med </span><span class="pun">=</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">advance</span><span class="pun">(</span><span class="pln">med</span><span class="pun">,</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">size</span><span class="pun">()</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">2</span><span class="pun">);</span><span class="pln">

</span><span class="com">// الوسيط موجود في الموضع الثاني</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">nth_element</span><span class="pun">(</span><span class="pln">b</span><span class="pun">,</span><span class="pln"> med</span><span class="pun">,</span><span class="pln"> e</span><span class="pun">);</span><span class="pln">

</span><span class="com">// v[2] الوسيط الآن هو</span></pre>

<p>
	ولإيجاد <a data-ss1617022534="1" href="https://ar.wikipedia.org/wiki/%D8%AA%D8%AC%D8%B2%D9%8A%D8%A1_(%D8%A5%D8%AD%D8%B5%D8%A7%D8%A1)" rel="external nofollow">نقطة تجزئة من الدرجة p</a> ‏‏(p-th quantile‏‏)، سنغيّر بعض السطور أعلاه:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_58" style="">
<span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> pos </span><span class="pun">=</span><span class="pln"> p </span><span class="pun">*</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">distance</span><span class="pun">(</span><span class="pln">b</span><span class="pun">,</span><span class="pln"> e</span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">advance</span><span class="pun">(</span><span class="pln">nth</span><span class="pun">,</span><span class="pln"> pos</span><span class="pun">);</span></pre>

<p>
	ستكون نقطة التجزئة في الموضع <code>‎pos‎</code>.
</p>

<h2>
	<code>std::count</code>
</h2>

<p>
	تحسُب <code>std::count</code> عدد العناصر التي تساوي قيمةً معيّنة <code>val</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_60" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">InputIterator</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">typename</span><span class="pln"> iterator_traits </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">InputIterator</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">difference_type
count</span><span class="pun">(</span><span class="typ">InputIterator</span><span class="pln"> first</span><span class="pun">,</span><span class="pln"> </span><span class="typ">InputIterator</span><span class="pln"> last</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> T </span><span class="pun">&amp;</span><span class="pln"> val</span><span class="pun">);</span></pre>

<h3>
	المعاملات
</h3>

<ul>
<li>
		<code>‎first‎</code> - مكرّر يشير إلى بداية المجال. *<code>‎last‎</code> =&gt; مكرّر يشير إلى نهاية المجال.
	</li>
	<li>
		<code>‎val‎</code> - القيمة المراد حساب تكرار حدوثها في المجال.
	</li>
</ul>
<h3>
	القيمة المعادة
</h3>

<p>
	عدد العناصر التي تساوي (==) <code>val</code> في المجال. انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_62" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;vector&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;algorithm&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> std</span><span class="pun">;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> argc</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> argv</span><span class="pun">[])</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

    </span><span class="com">// إنشاء متجهة</span><span class="pln">
    </span><span class="typ">vector</span><span class="pln"> intVec</span><span class="pun">{</span><span class="lit">4</span><span class="pun">,</span><span class="lit">6</span><span class="pun">,</span><span class="lit">8</span><span class="pun">,</span><span class="lit">9</span><span class="pun">,</span><span class="lit">10</span><span class="pun">,</span><span class="lit">30</span><span class="pun">,</span><span class="lit">55</span><span class="pun">,</span><span class="lit">100</span><span class="pun">,</span><span class="lit">45</span><span class="pun">,</span><span class="lit">2</span><span class="pun">,</span><span class="lit">4</span><span class="pun">,</span><span class="lit">7</span><span class="pun">,</span><span class="lit">9</span><span class="pun">,</span><span class="lit">43</span><span class="pun">,</span><span class="lit">48</span><span class="pun">};</span><span class="pln"> 

    </span><span class="com">//9, 55, 101 حساب مرات حدوث</span><span class="pln">
    </span><span class="typ">size_t</span><span class="pln"> count_9 </span><span class="pun">=</span><span class="pln"> count</span><span class="pun">(</span><span class="pln">intVec</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> intVec</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> </span><span class="lit">9</span><span class="pun">);</span><span class="pln"> </span><span class="com">//occurs twice</span><span class="pln">
    </span><span class="typ">size_t</span><span class="pln"> count_55 </span><span class="pun">=</span><span class="pln"> count</span><span class="pun">(</span><span class="pln">intVec</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> intVec</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> </span><span class="lit">55</span><span class="pun">);</span><span class="pln"> </span><span class="com">//occurs once</span><span class="pln">
    </span><span class="typ">size_t</span><span class="pln"> count_101 </span><span class="pun">=</span><span class="pln"> count</span><span class="pun">(</span><span class="pln">intVec</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> intVec</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> </span><span class="lit">101</span><span class="pun">);</span><span class="pln"> </span><span class="com">//occurs once</span><span class="pln">

    </span><span class="com">// اطبع النتيجة</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"There are "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> count_9 </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" 9s"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"There is "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> count_55 </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" 55"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"There is "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> count_101 </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" 101"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> ends</span><span class="pun">;</span><span class="pln">

  </span><span class="com">// 4 ابحث عن أول عنصر في المتجهة يساوي</span><span class="pln">
    </span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="typ">iterator</span><span class="pln"> itr_4 </span><span class="pun">=</span><span class="pln"> find</span><span class="pun">(</span><span class="pln">intVec</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> intVec</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> </span><span class="lit">4</span><span class="pun">);</span><span class="pln">

   </span><span class="com">// حساب مرات حدوثه في المتجه</span><span class="pln">
    </span><span class="typ">size_t</span><span class="pln"> count_4 </span><span class="pun">=</span><span class="pln"> count</span><span class="pun">(</span><span class="pln">itr_4</span><span class="pun">,</span><span class="pln"> intVec</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> itr_4</span><span class="pun">);</span><span class="pln"> </span><span class="com">// should be 2</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"There are "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> count_4 </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> itr_4 </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الناتج سيكون:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_64" style="">
<span class="typ">There</span><span class="pln"> are </span><span class="lit">2</span><span class="pln"> </span><span class="lit">9s</span><span class="pln">
</span><span class="typ">There</span><span class="pln"> is </span><span class="lit">1</span><span class="pln"> </span><span class="lit">55</span><span class="pln">
</span><span class="typ">There</span><span class="pln"> is </span><span class="lit">0</span><span class="pln"> </span><span class="lit">101</span><span class="pln">
</span><span class="typ">There</span><span class="pln"> are </span><span class="lit">2</span><span class="pln"> </span><span class="lit">4</span></pre>

<h2>
	<code>std::count_if</code>
</h2>

<p>
	تحسب <code>std::count_if</code> عدد العناصر في المجال التي تحقّق شرطًا معينًا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_66" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">InputIterator</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">UnaryPredicate</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">typename</span><span class="pln"> iterator_traits </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">InputIterator</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">difference_type
count_if</span><span class="pun">(</span><span class="typ">InputIterator</span><span class="pln"> first</span><span class="pun">,</span><span class="pln"> </span><span class="typ">InputIterator</span><span class="pln"> last</span><span class="pun">,</span><span class="pln"> </span><span class="typ">UnaryPredicate</span><span class="pln"> red</span><span class="pun">);</span></pre>

<h3>
	المعاملات
</h3>

<ul>
<li>
		<code>‎first‎</code> - مكرّر يشير إلى بداية المجال.
	</li>
	<li>
		<code>‎last‎</code> - مكرّر يشير إلى نهاية المجال.
	</li>
	<li>
		<code>‎red‎</code> - دالّة شرطية (تعيد إما <code>true</code> أو <code>false</code>).
	</li>
</ul>
<h3>
	القيمة المعادة
</h3>

<p>
	عدد العناصر في المجال التي تحقّق الشرط. انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_751_68" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;vector&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;algorithm&gt;</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> std</span><span class="pun">;</span><span class="pln">
</span><span class="com">/*
عرِّف بعض الدوال لاستخدامها كشروط
*/</span><span class="pln">

</span><span class="com">// فرديا number إن كان true إعادة </span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> isOdd</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> i </span><span class="pun">%</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// أكبر من قيمة وسيط المنشِئ number  إن كان true كائن دالي يعيد</span><span class="pln">
provided
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Greater</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> _than</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Greater</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> th</span><span class="pun">):</span><span class="pln"> _than</span><span class="pun">(</span><span class="pln">th</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">bool</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">()(</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> i </span><span class="pun">&gt;</span><span class="pln"> _than</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> argc</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> argv</span><span class="pun">[])</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

    </span><span class="com">// أنشئ متجهًا</span><span class="pln">
   </span><span class="typ">vector</span><span class="pln"> myvec </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="lit">5</span><span class="pun">,</span><span class="lit">8</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">7</span><span class="pun">,</span><span class="lit">6</span><span class="pun">,</span><span class="lit">4</span><span class="pun">,</span><span class="lit">5</span><span class="pun">,</span><span class="lit">2</span><span class="pun">,</span><span class="lit">1</span><span class="pun">,</span><span class="lit">5</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">6</span><span class="pun">,</span><span class="lit">9</span><span class="pun">,</span><span class="lit">7</span><span class="pun">};</span><span class="pln"> 

    </span><span class="com">// لحساب عدد العناصر الزوجية lambda استخدام دالّة</span><span class="pln">
    </span><span class="typ">size_t</span><span class="pln"> evenCount </span><span class="pun">=</span><span class="pln"> count_if</span><span class="pun">(</span><span class="pln">myvec</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> myvec</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> </span><span class="pun">[](</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> i </span><span class="pun">%</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">});</span><span class="pln"> </span><span class="com">// &gt;=  C++11</span><span class="pln">

    </span><span class="com">// استخدام مؤشّر دالّة لحساب عدد الأعداد الفردية في النصف الأول من المتجهة</span><span class="pln">
    </span><span class="typ">size_t</span><span class="pln"> oddCount </span><span class="pun">=</span><span class="pln"> count_if</span><span class="pun">(</span><span class="pln">myvec</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> myvec</span><span class="pun">.</span><span class="pln">end</span><span class="pun">()</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> myvec</span><span class="pun">.</span><span class="pln">size</span><span class="pun">()</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> isOdd</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// استخدام كائن دالّي لحساب عدد العناصر الأصغر من 5</span><span class="pln">
    </span><span class="typ">size_t</span><span class="pln"> greaterCount </span><span class="pun">=</span><span class="pln"> count_if</span><span class="pun">(</span><span class="pln">myvec</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> myvec</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> </span><span class="typ">Greater</span><span class="pun">(</span><span class="lit">5</span><span class="pun">));</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"vector size: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> myvec</span><span class="pun">.</span><span class="pln">size</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"even numbers: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> evenCount </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" found"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"odd numbers: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> oddCount </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" found"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"numbers &gt; 5: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> greaterCount </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" found"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الناتج سيكون:
</p>

<pre class="ipsCode" id="ips_uid_751_70">
vector size: 15
even numbers: 7 found
odd numbers: 4 found
numbers &gt; 5: 6 found
</pre>

<p>
	هذا الدرس جزء من <a data-ss1617022534="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 62: Standard Library Algorithms من كتاب <a data-ss1617022534="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">953</guid><pubDate>Mon, 10 Aug 2020 18:00:00 +0000</pubDate></item><item><title>&#x645;&#x627; &#x64A;&#x62C;&#x62F;&#x631; &#x628;&#x643; &#x645;&#x639;&#x631;&#x641;&#x62A;&#x647; &#x639;&#x645;&#x627; &#x641;&#x64A; &#x627;&#x644;&#x645;&#x643;&#x62A;&#x628;&#x629; &#x627;&#x644;&#x642;&#x64A;&#x627;&#x633;&#x64A;&#x629; std &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D9%85%D8%A7-%D9%8A%D8%AC%D8%AF%D8%B1-%D8%A8%D9%83-%D9%85%D8%B9%D8%B1%D9%81%D8%AA%D9%87-%D8%B9%D9%85%D8%A7-%D9%81%D9%8A-%D8%A7%D9%84%D9%85%D9%83%D8%AA%D8%A8%D8%A9-%D8%A7%D9%84%D9%82%D9%8A%D8%A7%D8%B3%D9%8A%D8%A9-std-%D9%81%D9%8A-cpp-r952/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_08/31.png.1f84caded2cdedfca8d6ae0c27f6c61d.png" /></p>

<h2>
	std::optional: القيم الاختيارية
</h2>

<p>
	تُستخدم القيم الاختيارية (المعروفة أيضًا باسم "أنواع الشّك") لتمثيل نوع قد يكون محتواه موجودًا أو لا، وقد قُدِّمت في C++‎ 17 على هيئة صنف <code>‎std::optional‎</code>. فمثلًا، قد يحتوي كائن من النوع <code>‎std::optional&lt;int&gt;‎</code> على قيمة من النوع <code>‎int‎</code>، أو قد لا يحتوي على أيّ قيمة. وتُستخدَم القيم الاختيارية إمّا لتمثيل قيمة قد لا تكون موجودة، أو كنوعٍ للقيمة المعادة من دالّة قد تفشل أحيانًا في إعادة نتيجة ذات معنى.
</p>

<h3>
	استخدام قيمة اختيارية لتمثيل غياب القيمة
</h3>

<p>
	كانت المؤشّرات التي تحمل القيمة <code>‎nullptr‎</code> قبل C++‎ 17 تمثّل عدم وجود أيّ قيمة، يعد هذا حلاً جيدًا للكائنات الكبيرة التي خُصِّصت ديناميكيًا وتُدار بواسطة مؤشّرات. لكن لا يعمل هذا الحلّ بشكل جيّد مع الأنواع الصغيرة أو الأوّلية (primitive) مثل <code>‎int‎</code>، والتي نادرًا ما تُخصّص أو تُدار ديناميكيًا من قبل المؤشّرات، ويوفّر <code>‎std::optional‎</code> حلاً مثاليًا لهذه المشكلة الشائعة.
</p>

<p>
	في المثال أدناه، عرّفنا البنية <code>Person‎</code>، والتي تمثل شخصًا، هذا الشخص يمكنه أن يمتلك حيوانًا أليفًا (pet)، لكنّ ذلك ليس ضروريًا. ولكي نخبر المصرّف بأنّ الحقل <code>pet</code> اختياري هنا، فسنُصرّح عنه بواسطة المُغلّف <code>‎std::optional‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_6" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;optional&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;string&gt;</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Animal</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">string name</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Person</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">string name</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">optional </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Animal</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> pet</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Person</span><span class="pln"> person</span><span class="pun">;</span><span class="pln">
    person</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> </span><span class="str">"John"</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">person</span><span class="pun">.</span><span class="pln">pet</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> person</span><span class="pun">.</span><span class="pln">name </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"'s pet's name is "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln">
            person</span><span class="pun">.</span><span class="pln">pet </span><span class="pun">-</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> name </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> person</span><span class="pun">.</span><span class="pln">name </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" is alone."</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	القيم الاختيارية كقيمة معادة
</h3>

<p>
	انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_8" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">optional </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">float</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> divide</span><span class="pun">(</span><span class="typ">float</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">float</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">b </span><span class="pun">!=</span><span class="pln"> </span><span class="lit">0.</span><span class="pln"> f</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> a </span><span class="pun">/</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في المثال أعلاه، سنعيد الكسر <code>‎a/b‎</code>، ولكن إذا لم يكن الكسر مُعرّفا (إن كان <code>‎b‎</code> يساوي 0 مثلًا)، فسَنعيد القيمة الاختيارية الفارغة. هذا مثال أكثر تعقيدًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_10" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Range</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Pred</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> find_if</span><span class="pun">(</span><span class="pln"> </span><span class="typ">Range</span><span class="pun">&amp;&amp;</span><span class="pln"> r</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Pred</span><span class="pun">&amp;&amp;</span><span class="pln"> p </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">begin</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">end</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">auto</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> begin</span><span class="pun">(</span><span class="pln">r</span><span class="pun">),</span><span class="pln"> e </span><span class="pun">=</span><span class="pln"> end</span><span class="pun">(</span><span class="pln">r</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">auto</span><span class="pln"> r </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">find_if</span><span class="pun">(</span><span class="pln">b</span><span class="pun">,</span><span class="pln"> e</span><span class="pun">,</span><span class="pln"> p</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> </span><span class="typ">iterator</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">r</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">r </span><span class="pun">==</span><span class="pln"> e</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">optional </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">iterator</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">();</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">optional </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">iterator</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">r</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Range</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> find</span><span class="pun">(</span><span class="pln"> </span><span class="typ">Range</span><span class="pun">&amp;&amp;</span><span class="pln"> r</span><span class="pun">,</span><span class="pln"> T </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> t </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> find_if</span><span class="pun">(</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="typ">Range</span><span class="pun">&gt;(</span><span class="pln">r</span><span class="pun">),</span><span class="pln"> </span><span class="pun">[&amp;</span><span class="pln">t</span><span class="pun">](</span><span class="kwd">auto</span><span class="pun">&amp;&amp;</span><span class="pln"> x</span><span class="pun">){</span><span class="kwd">return</span><span class="pln"> x</span><span class="pun">==</span><span class="pln">t</span><span class="pun">;}</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	تبحث الدالّة <code>‎‎find( some_range, 7 )‎</code> في الحاوية أو النطاق <code>‎some_range‎</code> عن شيء يساوي العدد <code>‎7‎</code>، وتفعل الدالة <code>‎find_if‎</code> عبر دالّة شرطية (predicate)، فتعيد إمّا قيمة اختيارية فارغة إذا لم يُعثر على أيّ شيء يساوي العدد <code>‎7‎</code>، أو عنصرًا اختياريا يحتوي على <a data-ss1617022533="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-8-%D8%A7%D9%84%D9%85%D9%83%D8%B1%D8%A7%D8%B1%D8%A7%D8%AA-iterators-%D9%81%D9%8A-cpp-r892/" rel="">مُكرّر</a> إلى العنصر في حال كان موجودًا. هذا يتيح لك القيام بما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_12" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">find</span><span class="pun">(</span><span class="pln">vec</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// code</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	أو حتى:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_14" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> oit </span><span class="pun">=</span><span class="pln"> find</span><span class="pun">(</span><span class="pln">vec</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    vec</span><span class="pun">.</span><span class="pln">erase</span><span class="pun">(</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> oit</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	دون الحاجة إلى استخدام مُكرّرات begin/end أو إجراء الاختبارات.
</p>

<h3>
	value_or
</h3>

<p>
	انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_16" style="">
<span class="kwd">void</span><span class="pln"> print_name</span><span class="pun">(</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">ostream</span><span class="pun">&amp;</span><span class="pln"> os</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">optional</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> name </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="str">"Name is: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> name</span><span class="pun">.</span><span class="pln">value_or</span><span class="pun">(</span><span class="str">"&lt;name missing&gt;"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يعيد التابع <code>‎value_or‎</code> القيمة المخزّنة في القيمة الاختيارية، أو يعيد الوسيط إذا لم يكن هناك أيّ شيء مُخزّن. يتيح لك هذا إمكانية أخذ القيمة الاختيارية (التي يمكن أن تكون فارغة) وتحديد سلوك افتراضي عندما تكون بحاجة إلى قيمة، وهكذا الطريقة، يمكن ترك تحديد "السلوك الافتراضي" إلى أن تكون هناك حاجة إليه، بدلًا من إنشاء قيمة افتراضية داخل مُحرِّك ما.
</p>

<h3>
	مقاربات أخرى للقيم الاختيارية
</h3>

<p>
	هناك العديد من الطرق الأخرى لحلّ المشكلة التي تحلها القيم الاختياريّة <code>‎std::optional‎</code>، لكن لا طريقة كاملة من تلك الطرق:
</p>

<h4>
	القيم الاختيارية مقابل المؤشّر
</h4>

<p>
	في بعض الحالات، يمكننا تمثيل "اختياريّةِ كائنٍ" عبر توفير مؤشّر يشير إلى كائن موجود أو مؤشّر فارغ <code>‎nullptr‎</code> للإشارة إلى فشل العمليّة. ولكنّ استخدام هذه الطريقة يقتصر على الحالات التي تكون فيها الكائنات موجودة بالفعل - بالمقابل، يمكن للقيم الاختيارية <code>‎optional‎</code> أن تُستخدَم لإعادة كائنات جديدة دون الحاجة إلى تخصيص الذاكرة.
</p>

<h4>
	القيم الاختيارية مقابل القيم التنبيهية
</h4>

<p>
	من المقاربات الشائعة استخدام قيمة خاصّة للإشارة إلى أنّ القيمة لا معنى لها، وقد تكون هذه القيمة مثلًا 0 أو ‎-1 بالنسبة للأعداد الصحيحة، أو <code>‎nullptr‎</code> بالنسبة للمؤشّرات.
</p>

<p>
	مثلًا، لنفترض أنّ هناك دالّة تحاول العثور على فهرس أول ظهور لحرف في سلسلة نصية، في حال كان الحرف موجودًا في السلسلة النصية، فستعيد فهرس أول ظهور له، أمّا في حال لم يكن موجودًا، فستعيد القيمة ‎-1 للدلالة على أنّ الحرف غير موجود في السلسلة النصية. القيمة ‎-1 تمثل القيمة التنبيهية، لأنها تنبّهنا إلى أمر ما (في هذا المثال، تنبِّهنا إلى عدم وجود الحرف المبحوث عنه في السلسلة النصية).
</p>

<p>
	المشكلة في هذه المقاربة أنّها تقلل من مساحة القيم الصالحة (لا يمكنك التمييز بين القيمة 0 الصالحة والقيمة 0 التي لا معنى لها)، وليست كل الأنواع فيها خيار طبيعي للقيم التنبيهية.
</p>

<h4>
	القيم الاختيارية مقابل الأزواج std::pair<bool t="">‎</bool>,&gt;
</h4>

<p>
	من المقاربات الشائعة أيضًا توفير زوج يكون أحد عُنصَريه قيمةً بوليانية <code>‎bool‎</code> للإشارة إلى كون القيمة ذات معنى أم لا، ويشترط هذا أن يكون نوع القيمة قابلًا للإنشاء افتراضيًا (default-constructible) في حالة حدوث خطأ، وهو أمر غير ممكن في بعض الأنواع، وقد يكون ممكنًا ولكن غير مرغوب بالنسبة لأنواع أخرى. بالمقابل، لا تحتاج القيم الاختيارية <code>‎optional&lt;T&gt;‎</code> في حال حدوث خطأ إلى بناء أي شيء.
</p>

<h3>
	استخدام القيم الاختيارية لتمثيل فشل دالة
</h3>

<p>
	قبل C++‎ 17، كانت الدوالّّ تمثِّل الفشلَ عادة بإحدى الطرق التالية:
</p>

<ul>
<li>
		إعادة مؤشّر فارغ.
	</li>
	<li>
		على سبيل المثال، استدعاء دالّة <code>‎Delegate *App::get_delegate()‎</code> على نسخة من الصنف <code>‎App‎</code> ليس لها مُفوّض (delegate) سيعيد <code>‎nullptr‎</code>.
	</li>
	<li>
		يُعدّ هذا حلاً جيدًا للكائنات التي خُصِّصت ديناميكيًا أو الكائنات الكبيرة التي تُدار عبر المُؤشّرات، لكنه ليس حلاً جيدًا بالنسبة للكائنات الصغيرة التي عادةً ما تكون مرصوصة (stack-allocated) وتُمرّر عن طريق النسخ.
	</li>
	<li>
		تحجز قيمة محدّدة من النوع المُعاد للإشارة إلى الفشل.
	</li>
	<li>
		على سبيل المثال، قد يؤدي استدعاء دالّة <code>‎unsigned shortest_path_distance(Vertex a, Vertex b)‎</code> على رأسين (vertices) غير مُتصلين إلى إعادة 0 للإشارة إلى هذه الحقيقة.
	</li>
	<li>
		يتم إقران القيمة المُعادة مع قيمة بوليانية <code>‎bool‎</code> لتحديد ما إذا كانت القيمة المعادة ذات معنى أم لا.
	</li>
	<li>
		على سبيل المثال، يؤدي استدعاء دالّة <code>‎std::pair&lt;int, bool&gt; parse(const std::string &amp;str)‎</code> باستخدام وسيط يحتوي سلسلة نصّية لا تتضمّن عددًا صحيحًا إلى إعادة زوج يضمّ عددًا صحيحا غير محدد وقيمة بوليانية تساوي <code>‎false‎</code>.
	</li>
</ul>
<p>
	في هذا المثال، يُعطى لزيد حيوانين أليفَين، سوسن وسوسان، ثم تُستدعى الدالّة <code>‎Person::pet_with_name()‎</code> لاسترداد الكلب "وافي". ونظرًا لأنّ زيد لا يملك كلبًا باسم "وافي"، فإن الدالّة ستفشل، وستُعاد القيمة <code>‎std::nullopt‎</code> بدلاً من ذلك.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_18" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;optional&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;string&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;vector&gt;</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Animal</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">string name</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Person</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">string name</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Animal</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> pets</span><span class="pun">;</span><span class="pln">

    std</span><span class="pun">::</span><span class="pln">optional </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Animal</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> pet_with_name</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&amp;</span><span class="pln"> name</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Animal</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> pet</span><span class="pun">:</span><span class="pln"> pets</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">pet</span><span class="pun">.</span><span class="pln">name </span><span class="pun">==</span><span class="pln"> name</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> pet</span><span class="pun">;</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">nullopt</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Person</span><span class="pln"> john</span><span class="pun">;</span><span class="pln">
    zaid</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> </span><span class="str">"زيد"</span><span class="pun">;</span><span class="pln">

    </span><span class="typ">Animal</span><span class="pln"> susan</span><span class="pun">;</span><span class="pln">
    susan</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> </span><span class="str">"سوسن"</span><span class="pun">;</span><span class="pln">
    zaid</span><span class="pun">.</span><span class="pln">pets</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">susan</span><span class="pun">);</span><span class="pln">

    </span><span class="typ">Animal</span><span class="pln"> susanne</span><span class="pun">;</span><span class="pln">
    susanne</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> </span><span class="str">"سوسان"</span><span class="pun">;</span><span class="pln">
    zaid</span><span class="pun">.</span><span class="pln">pets</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">susanne</span><span class="pun">);</span><span class="pln">

    std</span><span class="pun">::</span><span class="pln">optional </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Animal</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> dog </span><span class="pun">=</span><span class="pln"> john</span><span class="pun">.</span><span class="pln">pet_with_name</span><span class="pun">(</span><span class="str">"وافي"</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">dog</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"يملك زيد حيوانًا أليفًا اسمه وافي"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;”لا</span><span class="pln"> </span><span class="pun">يملك</span><span class="pln"> </span><span class="pun">زيد</span><span class="pln"> </span><span class="pun">حيوانًا</span><span class="pln"> </span><span class="pun">أليفًا</span><span class="pln"> </span><span class="pun">اسمه</span><span class="pln"> </span><span class="pun">وافي</span><span class="str">"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	std::function: تغليف الكائنات القابلة للاستدعاء
</h2>

<p>
	يوضح المثال التالي طريقة استخدام <code>std::function</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_20" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;functional&gt;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln"> function </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">(</span><span class="typ">int</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> myFuncObj</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> theFunc</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&amp;</span><span class="pln"> s</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> s </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">": "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> i </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> argc</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> argv</span><span class="pun">[])</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    myFuncObj </span><span class="pun">=</span><span class="pln"> theFunc</span><span class="pun">;</span><span class="pln">
    myFuncObj</span><span class="pun">(</span><span class="lit">10</span><span class="pun">,</span><span class="pln"> </span><span class="str">"hello world"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	استخدام std::function مع std::bind
</h3>

<p>
	إن احتجت إلى استدعاء دالّة مع تمرير وسائط إليها فإنّ استخدام <code>‎std::function‎</code> مع <code>‎std::bind‎</code> سيعطيك حلولًا فعّالة للغاية كما هو موضّح أدناه.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_22" style="">
<span class="kwd">class</span><span class="pln"> A </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln"> function </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">(</span><span class="typ">int</span><span class="pun">,</span><span class="pln">
            </span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> m_CbFunc </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">nullptr</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">m_CbFunc</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            m_CbFunc</span><span class="pun">(</span><span class="lit">100</span><span class="pun">,</span><span class="pln"> </span><span class="str">"event fired"</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> B </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        B</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">auto</span><span class="pln"> aFunc </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">bind</span><span class="pun">(</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> B</span><span class="pun">::</span><span class="pln">eventHandler</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">placeholders</span><span class="pun">::</span><span class="pln">_1</span><span class="pun">,</span><span class="pln">
                std</span><span class="pun">::</span><span class="pln">placeholders</span><span class="pun">::</span><span class="pln">_2</span><span class="pun">);</span><span class="pln">
            anObjA</span><span class="pun">.</span><span class="pln">m_CbFunc </span><span class="pun">=</span><span class="pln"> aFunc</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> eventHandler</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">,</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&amp;</span><span class="pln"> s</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> s </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">": "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> i </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">DoSomethingOnA</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        anObjA</span><span class="pun">.</span><span class="pln">foo</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    A anObjA</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> argc</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> argv</span><span class="pun">[])</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    B anObjB</span><span class="pun">;</span><span class="pln">
    anObjB</span><span class="pun">.</span><span class="typ">DoSomethingOnA</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	ربط std::function مع نوع آخر قابل للاستدعاء
</h3>

<p>
	يوضح المثال التالي كيفية استخدام <code>std::function</code> لاستدعاء دالة من نمط C، ودالة تابعة لصنف، وعامل <code>()operator</code>، ودالة لامدا. ويتم استدعاء الدالة من خلال الوسائط الصحيحة ووسائط بترتيب مختلف، وكذلك بأنواع وأعداد مختلفة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_24" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;functional&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;vector&gt;</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">placeholders</span><span class="pun">;</span><span class="pln">
</span><span class="com">// دالّة بسيطة لتُستدعى</span><span class="pln">
</span><span class="kwd">double</span><span class="pln"> foo_fn</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> </span><span class="typ">float</span><span class="pln"> y</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> z</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">double</span><span class="pln"> res </span><span class="pun">=</span><span class="pln"> x </span><span class="pun">+</span><span class="pln"> y </span><span class="pun">+</span><span class="pln"> z</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"foo_fn called with arguments: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln">
        x </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> y </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> z </span><span class="pun">&lt;&lt;</span><span class="pln">
        </span><span class="str">" result is : "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> res </span><span class="pun">&lt;&lt;</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> res</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// بنية مع دالة تابعة لاستدعائها</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> foo_struct </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// الدالة المراد استدعاؤها</span><span class="pln">
    </span><span class="kwd">double</span><span class="pln"> foo_fn</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> </span><span class="typ">float</span><span class="pln"> y</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> z</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">double</span><span class="pln"> res </span><span class="pun">=</span><span class="pln"> x </span><span class="pun">+</span><span class="pln"> y </span><span class="pun">+</span><span class="pln"> z</span><span class="pun">;</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"foo_struct::foo_fn called with arguments: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln">
            x </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> y </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> z </span><span class="pun">&lt;&lt;</span><span class="pln">
            </span><span class="str">" result is : "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> res </span><span class="pun">&lt;&lt;</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> res</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// هذا التابع له بصمة مختلفة، مع ذلك يمكن استخدامه</span><span class="pln">
    </span><span class="com">// لاحظ أنّ ترتيب المعاملات قد تغير</span><span class="pln">
    </span><span class="kwd">double</span><span class="pln"> foo_fn_4</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> z</span><span class="pun">,</span><span class="pln"> </span><span class="typ">float</span><span class="pln"> y</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> xx</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">double</span><span class="pln"> res </span><span class="pun">=</span><span class="pln"> x </span><span class="pun">+</span><span class="pln"> y </span><span class="pun">+</span><span class="pln"> z </span><span class="pun">+</span><span class="pln"> xx</span><span class="pun">;</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"foo_struct::foo_fn_4 called with arguments: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln">
            x </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> z </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> y </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> xx </span><span class="pun">&lt;&lt;</span><span class="pln">
            </span><span class="str">" result is : "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> res </span><span class="pun">&lt;&lt;</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> res</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// جعل الكائن بأكمله قابلا للاستدعاء operator() التحميل الزائد للعامل</span><span class="pln">
    </span><span class="kwd">double</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">()(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> </span><span class="typ">float</span><span class="pln"> y</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> z</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">double</span><span class="pln"> res </span><span class="pun">=</span><span class="pln"> x </span><span class="pun">+</span><span class="pln"> y </span><span class="pun">+</span><span class="pln"> z</span><span class="pun">;</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"foo_struct::operator() called with arguments: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln">
            x </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> y </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> z </span><span class="pun">&lt;&lt;</span><span class="pln">
            </span><span class="str">" result is : "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> res </span><span class="pun">&lt;&lt;</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> res</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">(</span><span class="kwd">void</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// typedefs</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> function_type </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln"> function </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">double</span><span class="pun">(</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">float</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">double</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
    </span><span class="com">// foo_struct نسخة</span><span class="pln">
    foo_struct fs</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// سنخزّن هنا كل الدوالّ المربوطة</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> function_type </span><span class="pun">&gt;</span><span class="pln"> bindings</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// var #1 - يمكن استخدام دالّة بسيطة وحسب</span><span class="pln">
    function_type var1 </span><span class="pun">=</span><span class="pln"> foo_fn</span><span class="pun">;</span><span class="pln">
    bindings</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">var1</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// var #2 - يمكنك استخدام تابع</span><span class="pln">
    function_type var2 </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">bind</span><span class="pun">(</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> foo_struct</span><span class="pun">::</span><span class="pln">foo_fn</span><span class="pun">,</span><span class="pln"> fs</span><span class="pun">,</span><span class="pln"> _1</span><span class="pun">,</span><span class="pln"> _2</span><span class="pun">,</span><span class="pln"> _3</span><span class="pun">);</span><span class="pln">
    bindings</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">var2</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// var #3 - يمكنك استخدام تابع مع بصمة مختلفة</span><span class="pln">
    </span><span class="com">// لها عدد مختلف من المعاملات ومن أنواع مختلفة foo_fn_4 </span><span class="pln">
    function_type var3 </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">bind</span><span class="pun">(&amp;</span><span class="pln">foo_struct</span><span class="pun">::</span><span class="pln">foo_fn_4</span><span class="pun">,</span><span class="pln"> fs</span><span class="pun">,</span><span class="pln"> _1</span><span class="pun">,</span><span class="pln"> _3</span><span class="pun">,</span><span class="pln"> _2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0l</span><span class="pun">);</span><span class="pln">
    bindings</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">var3</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// var #4 -  مُحمَّل تحميلا زائدا operator() يمكنك استخدام كائن ذي معامل</span><span class="pln">
    function_type var4 </span><span class="pun">=</span><span class="pln"> fs</span><span class="pun">;</span><span class="pln">
    bindings</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">var4</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// var #5 - lambda يمكنك استخدام دالّة</span><span class="pln">
    function_type var5 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[](</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> </span><span class="typ">float</span><span class="pln"> y</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> z</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">double</span><span class="pln"> res </span><span class="pun">=</span><span class="pln"> x </span><span class="pun">+</span><span class="pln"> y </span><span class="pun">+</span><span class="pln"> z</span><span class="pun">;</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"lambda  called with arguments: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln">
            x </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> y </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> z </span><span class="pun">&lt;&lt;</span><span class="pln">
            </span><span class="str">" result is : "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> res </span><span class="pun">&lt;&lt;</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> res</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
    bindings</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">var5</span><span class="pun">);</span><span class="pln">

    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Test stored functions with arguments: x = 1, y = 2, z = 3"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> f</span><span class="pun">:</span><span class="pln"> bindings</span><span class="pun">)</span><span class="pln">
        f</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">);</span><span class="pln">

</span><span class="pun">}</span></pre>

<p>
	انظر هذا <a data-ss1617022533="1" href="ideone.com/VIbkkZ" rel="">المثال الحي</a>.
</p>

<p>
	الناتج:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_26" style="">
<span class="typ">Test</span><span class="pln"> stored functions with arguments</span><span class="pun">:</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> y </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> z </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pln">
foo_fn called with arguments</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> result is </span><span class="pun">:</span><span class="pln"> </span><span class="lit">6</span><span class="pln">
foo_struct</span><span class="pun">::</span><span class="pln">foo_fn called with arguments</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> result is </span><span class="pun">:</span><span class="pln"> </span><span class="lit">6</span><span class="pln">
foo_struct</span><span class="pun">::</span><span class="pln">foo_fn_4 called with arguments</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> result is </span><span class="pun">:</span><span class="pln"> </span><span class="lit">6</span><span class="pln">
foo_struct</span><span class="pun">::</span><span class="kwd">operator</span><span class="pun">()</span><span class="pln"> called with arguments</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> result is </span><span class="pun">:</span><span class="pln"> </span><span class="lit">6</span><span class="pln">
lambda  called with arguments</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> result is </span><span class="pun">:</span><span class="pln"> </span><span class="lit">6</span></pre>

<h3>
	تخزين وسائط الدالة في صف std::tuple
</h3>

<p>
	تحتاج بعض البرامج إلى تخزين الوسائط إلى حين استدعاء بعض الدوالّ في المستقبل. ويوضّح هذا المثال كيفية استدعاء أيّ دالّة باستخدام الوسائط المخزّنة في صفّ <code>std::tuple</code>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_28" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;functional&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;tuple&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

 </span><span class="com">// دالّة بسيطة لاستدعائها</span><span class="pln">
</span><span class="kwd">double</span><span class="pln"> foo_fn</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> </span><span class="typ">float</span><span class="pln"> y</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> z</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">double</span><span class="pln"> res </span><span class="pun">=</span><span class="pln"> x </span><span class="pun">+</span><span class="pln"> y </span><span class="pun">+</span><span class="pln"> z</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"foo_fn called. x = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> x </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" y = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> y </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" z = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> z </span><span class="pun">&lt;&lt;</span><span class="pln">
        </span><span class="str">" res="</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> res</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> res</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// مساعِدات من أجل تسريع الصف.</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">struct</span><span class="pln"> seq </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> N</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">...</span><span class="pln">S </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">struct</span><span class="pln"> gens</span><span class="pun">:</span><span class="pln"> gens </span><span class="pun">&lt;</span><span class="pln"> N </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> N </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> S</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">...</span><span class="pln">S </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">struct</span><span class="pln"> gens </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> S</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">typedef</span><span class="pln"> seq </span><span class="pun">&lt;</span><span class="pln"> S</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> type</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="com">//استدعاء المساعِدات</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> FN</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> P</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">...</span><span class="pln">S </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">double</span><span class="pln"> call_fn_internal</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> FN </span><span class="pun">&amp;</span><span class="pln"> fn</span><span class="pun">,</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> P </span><span class="pun">&amp;</span><span class="pln"> params</span><span class="pun">,</span><span class="pln">
            </span><span class="kwd">const</span><span class="pln"> seq </span><span class="pun">&lt;</span><span class="pln"> S</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> fn</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">get </span><span class="pun">&lt;</span><span class="pln"> S </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">params</span><span class="pun">)...);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="com">// std::tuple استدعاء الدالّة مع الوسائط المُخزنة في</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">Ret</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pun">...</span><span class="typ">Args</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="typ">Ret</span><span class="pln"> call_fn</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln"> function </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Ret</span><span class="pun">(</span><span class="typ">Args</span><span class="pun">...)</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> fn</span><span class="pun">,</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">tuple </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Args</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> params</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> call_fn_internal</span><span class="pun">(</span><span class="pln">fn</span><span class="pun">,</span><span class="pln"> params</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> gens </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">...(</span><span class="typ">Args</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">type</span><span class="pun">());</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">(</span><span class="kwd">void</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

    </span><span class="com">// الوسائط</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">tuple </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">float</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> t </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_tuple</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// الدالّة المراد استدعاؤها</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln"> function </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">double</span><span class="pun">(</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">float</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">double</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> fn </span><span class="pun">=</span><span class="pln"> foo_fn</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// استدعاء الدالّة مع تمرير الوسائط المُخزّنة إليها</span><span class="pln">
    call_fn</span><span class="pun">(</span><span class="pln">fn</span><span class="pun">,</span><span class="pln"> t</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هذا <a data-ss1617022533="1" href="ideone.com/FZKALn" rel="">مثال حي</a>
</p>

<p>
	الناتج:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_30" style="">
<span class="pln">foo_fn called</span><span class="pun">.</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> y </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> z </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pln"> res</span><span class="pun">=</span><span class="lit">16</span></pre>

<h3>
	استخدام std::function مع تعابير لامدا والصنف std::bind
</h3>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_32" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;functional&gt;</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">placeholders</span><span class="pun">::</span><span class="pln">_1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// std::bind ستُستخدَم في مثال</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> stdf_foobar</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln"> function </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">(</span><span class="typ">int</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> moo</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> x </span><span class="pun">+</span><span class="pln"> moo</span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span><span class="pln"> </span><span class="com">// std::function moo استدعاء</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> foo </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">2</span><span class="pun">+</span><span class="pln">x</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> foo_2 </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> y</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">9</span><span class="pun">*</span><span class="pln">x </span><span class="pun">+</span><span class="pln"> y</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">

    </span><span class="com">/* مؤشّرات الدوالّ */</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> stdf_foobar</span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> foo</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 6 ( 2 + (2+2) )</span><span class="pln">
    </span><span class="com">// stdf_foobar(2, foo) يمكن أن تكون أيضا</span><span class="pln">

    </span><span class="com">/* Lambda تعابير */</span><span class="pln">
    </span><span class="com">/* std::function في كائن lambda يمكن تخزين دالّة مُغلقة من تعبير
     */</span><span class="pln">
   std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> stdf_foobar</span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln">
</span><span class="pun">[</span><span class="pln">capture_value</span><span class="pun">](</span><span class="typ">int</span><span class="pln"> param</span><span class="pun">)</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">7</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> capture_value </span><span class="pun">*</span><span class="pln"> param</span><span class="pun">;</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// result: 15 ==  value + (7 * capture_value * value) == 2 + (7 + 3 * 2)</span><span class="pln">

    </span><span class="com">/* std::bind تعابير */</span><span class="pln">
    </span><span class="com">/* std::bind يمكن تمرير نتيجة التعبير
     * مثلا عبر ربط المعاملات باستدعاء مؤشّر دالّة
     */</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> stdf_foobar</span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">bind</span><span class="pun">(</span><span class="pln">foo_2</span><span class="pun">,</span><span class="pln"> _1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">));</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> b </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// b == 23 == 2 + ( 9*2 + 3 )</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> stdf_foobar</span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">bind</span><span class="pun">(</span><span class="pln">foo_2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> _1</span><span class="pun">));</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> c </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// c == 49 == 2 + ( 9*5 + 2 )</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	الحمل الزائد للدوال (function overhead)
</h3>

<p>
	يمكن أن تتسبب <code>std::function‎</code> في حِمل زائد كبير لأنّ <code>std::function‎</code> لها دلالات قيمية (value semantics)، فسيكون من اللازم أن تنسخ أو تنقل ما استُدعِي إليها. ولكن بما أنها تستطيع أخذ كائن قابل للاستدعاء من أيّ نوع، فسيتعينّ عليها في كثير من الأحيان أن تخصّص ذاكرة ديناميكية بذلك.
</p>

<p>
	تحتوي بعض تطبيقات <code>‎function‎</code> على ما يسمى "تحسين الكائنات الصغيرة" (small object optimization)، وفيها تُخزّن الأنواع الصغيرة مثل مؤشّرات الدوالّ أو مؤشّرات الأعضاء أو الكائنات الدالّية (Functors) ذات الحالة الصغيرة، مباشرة في كائن الدالّة <code>‎function‎</code>. لكنّ هذا لن يعمل إلّا إن كان النوع قابلًا للإنشاء النقلي عند الاعتراض (noexcept move constructible). أيضًا، لا يتطلب معيار C++‎ أن توفّر جميع التطبيقات مثل هذا التحسين. إليك المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_34" style="">
<span class="com">// ملف الترويسة</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">MyPredicate</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">function</span><span class="pun">&lt;</span><span class="kwd">bool</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">MyValue</span><span class="pln"> </span><span class="pun">&amp;,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">MyValue</span><span class="pln"> </span><span class="pun">&amp;)&gt;;</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> </span><span class="typ">SortMyContainer</span><span class="pun">(</span><span class="typ">MyContainer</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">C</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">MyPredicate</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">pred</span><span class="pun">);</span><span class="pln">
</span><span class="com">// الملف المصدري</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> </span><span class="typ">SortMyContainer</span><span class="pun">(</span><span class="typ">MyContainer</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">C</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">MyPredicate</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">pred</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">sort</span><span class="pun">(</span><span class="pln">C</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> C</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> pred</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يُعدّ معامل القالب هو الحلّ المفضّل لـ <code>‎SortMyContainer‎</code>، ولكن إن افترضنا أنّ هذا غير ممكن أو غير مرغوب فيه لسبب من الأسباب، فلن تحتاج <code>‎SortMyContainer‎</code> إلى تخزين <code>‎pred‎</code> إلا في إطار استدعائها. ومع ذلك، فقد تُخصّص لـ <code>‎pred‎</code> ذاكرةً إن كان الكائن الدّالِّي (functor) المُعطى ذا حجم غير معروف.
</p>

<p>
	تخصّص <code>‎function‎</code> الذاكرة لأنّها تحتاج إلى شيءٍ لتنسخ أو تنقل إليه، كما أنها تأخذ ملكية الكائن القابل للاستدعاء الذي مُرِّر إليها، لكنّ <code>‎SortMyContainer‎</code> لا تحتاج إلى امتلاك المُستدعِي ولكنها تحتاج إلى مرجع إليه وحسب، لذا فلا داعي لاستخدام <code>‎function‎</code> هنا. كذلك لا يوجد أي نوع دالّة قياسي يشير حصرًا إلى كائنٍ قابل للاستدعاء، لذلك سيكون عليك أن تنتظر إيجاد حلّ لهذا، أو يمكنك التعايش مع الحمل الزائد.
</p>

<p>
	أيضّا، لا تملك <code>‎function‎</code> أيّ وسيلة فعّالة للتحكم في الموضع الذي تأتي منه تخصيصات الذاكرة الخاصّة بالكائن. صحيح أنّ لها مُنشئات تأخذ كائن تخصيص <code>‎allocator‎</code>، ولكنّ العديد من التقديمات لا تقدّمها بالشكل الصحيح … أو لا تقدما بتاتًا.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 17</strong>
</p>

<p>
	لم يعُد المنشئ <code>‎function‎</code> الذي يأخذ كائن تخصيصٍ <code>‎allocator‎</code> جزءًا من النوع. لذلك لا توجد أيّ طريقة لإدارة التخصيص. واعلم أن استدعاء <code>‎function‎</code> أبطأ من استدعاء المحتويات مباشرةً. كذلك يجب أن يكون الاستدعاء عبر <code>function</code> غير مباشر لأنّ نُسَخَ <code>‎function‎</code> يمكن أن تحتوي كائنًا قابلًا للاستدعاء، ويكافئ الحِمل الزائد الناتج عن استدعاء <code>‎function‎</code> الحِمل الزائد الناتج عن استدعاء دالّة وهمية.
</p>

<h2>
	std::forward_list: القوائم الإدراجية
</h2>

<p>
	النوع <code>std::forward_list</code> هو حاوية تدعم الإدراج السريع للعناصر من أي مكان فيها وكذلك إزالة تلك العناصر، لكنها لا تدعم الوصول العشوائي السريع.
</p>

<p>
	يُنفَّذ النوع <code>std::forward_list</code> كقائمة مرتبطة أحادية (singly-linked list)، وليس لها عمومًا أيّ حِمل زائد (overhead) مقارنة بتطبيقها في C. وتوفّر هذه الحاوية، مقارنة بـ <code>‎std::list‎</code>، مساحة تخزين أكثر كفاءة عند غياب الحاجة للتكرار ثنائي الاتجاه (bidirectional iteration). انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_36" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;forward_list&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;string&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">ostream </span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ostream </span><span class="pun">&amp;</span><span class="pln"> s</span><span class="pun">,</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">forward_list </span><span class="pun">&lt;</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> v</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        s</span><span class="pun">.</span><span class="pln">put</span><span class="pun">(</span><span class="str">'['</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">char</span><span class="pln"> comma</span><span class="pun">[</span><span class="lit">3</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="str">'\0'</span><span class="pun">,</span><span class="pln">
            </span><span class="str">' '</span><span class="pun">,</span><span class="pln">
            </span><span class="str">'\0'</span><span class="pln">
        </span><span class="pun">};</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> e</span><span class="pun">:</span><span class="pln"> v</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            s </span><span class="pun">&lt;&lt;</span><span class="pln"> comma </span><span class="pun">&lt;&lt;</span><span class="pln"> e</span><span class="pun">;</span><span class="pln">
            comma</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">','</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> s </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">']'</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// c++11 صياغة قائمة المهييء في</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">forward_list </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&gt;</span><span class="pln"> words1 </span><span class="pun">{</span><span class="pln">
        </span><span class="str">"the"</span><span class="pun">,</span><span class="pln">
        </span><span class="str">"frogurt"</span><span class="pun">,</span><span class="pln">
        </span><span class="str">"is"</span><span class="pun">,</span><span class="pln">
        </span><span class="str">"also"</span><span class="pun">,</span><span class="pln">
        </span><span class="str">"cursed"</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"words1: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> words1 </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// words2 == words1</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">forward_list </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&gt;</span><span class="pln"> words2</span><span class="pun">(</span><span class="pln">words1</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> words1</span><span class="pun">.</span><span class="pln">end</span><span class="pun">());</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"words2: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> words2 </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// words3 == words1</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">forward_list </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&gt;</span><span class="pln"> words3</span><span class="pun">(</span><span class="pln">words1</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"words3: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> words3 </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// words4 is {"Mo", "Mo", "Mo", "Mo", "Mo"}</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">forward_list </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&gt;</span><span class="pln"> words4</span><span class="pun">(</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Mo"</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"words4: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> words4 </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الناتج:
</p>

<pre class="ipsCode">
words1: [the, frogurt, is, also, cursed]
words2: [the, frogurt, is, also, cursed]
words3: [the, frogurt, is, also, cursed]
words4: [Mo, Mo, Mo, Mo, Mo]
</pre>

<h3>
	التوابع
</h3>

<p>
	إليك قائمة التوابع الخاصة بالنوع std::forward_list:
</p>

<table>
<thead><tr>
<th>
				اسم التابع
			</th>
			<th>
				التعريف
			</th>
		</tr></thead>
<tbody>
<tr>
<td>
				<code>operator=</code>
			</td>
			<td>
				يعيّن قيمًا إلى الحاوية
			</td>
		</tr>
<tr>
<td>
				<code>assign</code>
			</td>
			<td>
				يعيّن قيمًا إلى الحاوية
			</td>
		</tr>
<tr>
<td>
				<code>get_allocator</code>
			</td>
			<td>
				يعيد المخصِّص المرتبط به (associated allocator)
			</td>
		</tr>
<tr>
<td>
				<code>front</code>
			</td>
			<td>
				يصل إلى العنصر الأول
			</td>
		</tr>
<tr>
<td>
				<code>before_begin</code>
			</td>
			<td>
				يعيد مكررًا إلى العنصر قبل البداية
			</td>
		</tr>
<tr>
<td>
				<code>cbefore_begin</code>
			</td>
			<td>
				يعيد مكررًا ثابت إلى العنصر قبل البداية
			</td>
		</tr>
<tr>
<td>
				<code>begin</code>
			</td>
			<td>
				يعيد مكررًا إلى البداية
			</td>
		</tr>
<tr>
<td>
				<code>cbegin</code>
			</td>
			<td>
				يعيد مكررًا ثابت إلى البداية
			</td>
		</tr>
<tr>
<td>
				<code>end</code>
			</td>
			<td>
				يعيد مكررًا إلى النهاية
			</td>
		</tr>
<tr>
<td>
				<code>cend</code>
			</td>
			<td>
				يعيد مكررًا إلى النهاية
			</td>
		</tr>
<tr>
<td>
				<code>empty</code>
			</td>
			<td>
				يتحقق إن كانت الحاوية فارغة
			</td>
		</tr>
<tr>
<td>
				<code>max_size</code>
			</td>
			<td>
				يعيد الحد الأقصى للعدد الممكن من العناصر
			</td>
		</tr>
<tr>
<td>
				<code>clear</code>
			</td>
			<td>
				يمسح المحتويات
			</td>
		</tr>
<tr>
<td>
				<code>insert_after</code>
			</td>
			<td>
				يُدرِج عناصرًا بعد عنصر ما
			</td>
		</tr>
<tr>
<td>
				<code>emplace_after</code>
			</td>
			<td>
				ينشئ عنصرًا مكان عنصر آخر
			</td>
		</tr>
<tr>
<td>
				<code>erase_after</code>
			</td>
			<td>
				يمحو عنصرًا موجودا بعد عنصر ما
			</td>
		</tr>
<tr>
<td>
				<code>push_front</code>
			</td>
			<td>
				يدرج عنصرًا في البداية
			</td>
		</tr>
<tr>
<td>
				<code>emplace_front</code>
			</td>
			<td>
				ينشئ عنصرًا في البداية
			</td>
		</tr>
<tr>
<td>
				<code>pop_front</code>
			</td>
			<td>
				يزيل العنصر الأول
			</td>
		</tr>
<tr>
<td>
				<code>resize</code>
			</td>
			<td>
				يغير عدد العناصر المخزنة
			</td>
		</tr>
<tr>
<td>
				<code>swap</code>
			</td>
			<td>
				يبدل المحتويات
			</td>
		</tr>
<tr>
<td>
				<code>merge</code>
			</td>
			<td>
				يدمج قائمتين مرتبتين
			</td>
		</tr>
<tr>
<td>
				<code>splice_after</code>
			</td>
			<td>
				ينقل عناصر من قائمة أمامية أخرى
			</td>
		</tr>
<tr>
<td>
				<code>remove</code>
			</td>
			<td>
				يزيل العناصر التي تحقق شرطا محددا
			</td>
		</tr>
<tr>
<td>
				<code>remove_if</code>
			</td>
			<td>
				يزيل العناصر التي تحقق شرطا محددا
			</td>
		</tr>
<tr>
<td>
				<code>reverse</code>
			</td>
			<td>
				يعكس ترتيب العناصر
			</td>
		</tr>
<tr>
<td>
				<code>unique</code>
			</td>
			<td>
				يزيل العناصر المتساوية المتتالية
			</td>
		</tr>
<tr>
<td>
				<code>sort</code>
			</td>
			<td>
				يرتب العناصر
			</td>
		</tr>
</tbody>
</table>
<style type="text/css">
table {
    width: 100%;
}

thead {
    vertical-align: middle;
    text-align: center;
}

td, th {
    border: 1px solid #dddddd;
    text-align: right;
    padding: 8px;
    text-align: inherit;

}
tr:nth-child(even) {
    background-color: #dddddd;
}</style>
<h2>
	std::pair: الأزواج
</h2>

<h3>
	عوامل الموازنة
</h3>

<p>
	معامِلات هذه العوامل هي <code>‎lhs‎</code> و <code>‎rhs‎</code>:
</p>

<ul>
<li>
		<code>‎operator==‎</code> - يتحقّق هذا العامل من أنّ عناصر كلا الزوجين <code>‎lhs‎</code> و <code>‎rhs‎</code> متساويان، وتكون القيمة المُعادة هي <code>true</code> إن كان <code>lhs.first == rhs.first</code> و <code>lhs.second == rhs.second</code>، وإلّا فستكون <code>false</code>.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_39" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">pair </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> p1 </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">pair </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> p2 </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">p1 </span><span class="pun">==</span><span class="pln"> p2</span><span class="pun">)</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"equals"</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">else</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"not equal"</span><span class="pun">;</span><span class="pln"> </span><span class="com">// ستُظهر التعليمة هذا، لأن الزوجين غير متماثلين</span></pre>

<ul>
<li>
		<code>‎operator!=‎</code> - يتحقّق هذا العامل ممّا إذا كان أيّ من عناصر الزوجيين <code>‎lhs‎</code> و <code>‎rhs‎</code> غير متساويين، وتكون القيمة المُعادة هي<code>true</code> إن كان <code>‎lhs.first != rhs.first</code> أو <code>lhs.second != rhs.second</code>، وإلا فستُعاد القيمة <code>false</code>.
	</li>
	<li>
		<code>‎operator&lt;‎</code> - إذا كان <code>lhs.first&lt;rhs.first‎</code>، فسيُعيد <code>true</code> وإن كان <code>rhs.first&lt;lhs.first‎</code> فسيُعيد <code>false</code>. وكذلك إن كان <code>‎lhs.second&lt;rhs.second‎</code> فسيُعيد <code>‎true‎</code>، أما خلاف ذلك سيُعيد <code>‎false‎</code>.
	</li>
	<li>
		<code>‎operator&lt;=‎</code> - يُعيد <code>‎!(rhs&lt;lhs)‎</code>
	</li>
	<li>
		<code>‎operator&gt;‎</code> - يعيد <code>‎rhs&lt;lhs</code>
	</li>
	<li>
		<code>‎operator&gt;=‎</code> - يعيد <code>‎!(lhs&lt;rhs)‎</code>
	</li>
</ul>
<p>
	هذا مثال آخر يستخدم حاويات أزواج، ويستخدم العامل <code>‎operator&lt;‎</code> لترتيب الحاوية.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_41" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;utility&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;vector&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;algorithm&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;string&gt;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
 std</span><span class="pun">::</span><span class="typ">vector</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">pair</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&gt;&gt;</span><span class="pln"> v </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">    </span><span class="pun">{</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="str">"baz"</span><span class="pun">},</span><span class="pln">
</span><span class="pun">{</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="str">"bar"</span><span class="pun">},</span><span class="pln">
</span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="str">"foo"</span><span class="pun">}</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">sort</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">());</span><span class="pln">

    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> p</span><span class="pun">:</span><span class="pln"> v</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"("</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> p</span><span class="pun">.</span><span class="pln">first </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">","</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> p</span><span class="pun">.</span><span class="pln">second </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">") "</span><span class="pun">;</span><span class="pln">
        </span><span class="com">// (1,foo) (2,bar) (2,baz) :الناتج</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	إنشاء زوج والوصول إلى عناصره
</h3>

<p>
	تتيح لنا الأزواج أن نعامل كائِنين كما لو كانا كائنًا واحدًا، ويمكن إنشاء الأزواج بسهولة بمساعدة دالّة القالب <code>std::make_pair</code>. وهناك طريقة أخرى، وهي إنشاء زوج وتعيين عنصُريه (<code>‎first‎</code> و <code>‎second‎</code>) لاحقًا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_43" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;utility&gt;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">pair </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> p </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">);</span><span class="pln"> </span><span class="com">// إنشاء الزوج</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> p</span><span class="pun">.</span><span class="pln">first </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> p</span><span class="pun">.</span><span class="pln">second </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// الوصول إلى العناصر</span><span class="pln">

    </span><span class="com">// يمكننا أيضا إنشاء الزوج وتعيين عناصره لاحقا</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">pair </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> p1</span><span class="pun">;</span><span class="pln">
    p1</span><span class="pun">.</span><span class="pln">first </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln">
    p1</span><span class="pun">.</span><span class="pln">second </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> p1</span><span class="pun">.</span><span class="pln">first </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> p1</span><span class="pun">.</span><span class="pln">second </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">

  </span><span class="com">// يمكننا أيضا إنشاء زوج باستخدام منشئ</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">pair </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> p2 </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">pair </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> p2</span><span class="pun">.</span><span class="pln">first </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> p2</span><span class="pun">.</span><span class="pln">second </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	std::atomics: الأنواع الذرية
</h2>

<p>
	كل استنساخ (instantiation) وتخصيص للقالب <code>‎std::atomic‎</code> يعرّف نوعًا ذريًا (atomic type)، فإن قامت أحد الخيوط (threads) بالكتابة في كائن ذرّي أثناء قراءة مسلك آخر منه، فإنّ السّلوك سيكون مُعرّفًا بشكل جيد، ولن يحدث أيّ مشكل.
</p>

<p>
	إضافة إلى ذلك، قد يؤدّي الدخول إلى الكائنات الذرية إلى تهيئة تزامن بين الخيوط ويطلب دخولًا غير ذرّي للذاكرة (non-atomic memory accesses) كما هو مُعرَّف من قِبل <code>‎std::memory_order‎</code>. يمكن استنساخ <code>std::atomic</code> مع أيّ نوع قابل للنسخ (<code>‎TriviallyCopyable type T. std::atomic‎</code>)، لكن <code>std::atomic</code> ليست قابلة للنسخ أو النقل.
</p>

<p>
	توفّر المكتبة القياسية تخصيصات للقالب <code>std::atomic</code> للأنواع التالية:
</p>

<p>
	1) تعريف تخصيص كامل للنوع البولياني <code>‎bool‎</code>، وعُرِّفت قيمة التعريف النوعي (typedef) الخاصة به بحيث يُتعامل معه على أنّه نوع ذرّي <code>std::atomic&lt;T&gt;‎</code> غير مُخصَّص، فيما عدا أنّه ستكون له مخطط (layout) قياسي، ومنشئ افتراضي أولي، ومدمّرات واضحة، كما سيدعم صيغة التهيئة الإجمالية (aggregate initialization syntax):
</p>

<table>
<thead><tr>
<th>
				Typedef
			</th>
			<th>
				التخصيص
			</th>
		</tr></thead>
<tbody><tr>
<td>
				<code>std::atomic_bool</code>
			</td>
			<td>
				<code>std::atomic&lt;bool&gt;</code>
			</td>
		</tr></tbody>
</table>
<p>
	2) تخصيصات كاملة وتعريفات نوعية typedefs للأنواع العددية الصحيحة، كما يلي:
</p>

<table>
<thead><tr>
<th>
				Typedef
			</th>
			<th>
				التخصيص
			</th>
		</tr></thead>
<tbody>
<tr>
<td>
				<code>std::atomic_char</code>
			</td>
			<td>
				<code>std::atomic&lt;char</code>‎<code>&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_char</code>
			</td>
			<td>
				<code>std::atomic&lt;char&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_schar</code>
			</td>
			<td>
				<code>std::atomic&lt;signed char&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_uchar</code>
			</td>
			<td>
				<code>std::atomic&lt;unsigned char&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_short</code>
			</td>
			<td>
				<code>std::atomic&lt;short&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_ushort</code>
			</td>
			<td>
				<code>std::atomic&lt;unsigned short&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_int</code>
			</td>
			<td>
				<code>std::atomic&lt;int&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_uint</code>
			</td>
			<td>
				<code>std::atomic&lt;unsigned int&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_long</code>
			</td>
			<td>
				<code>std::atomic&lt;long&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_ulong</code>
			</td>
			<td>
				<code>std::atomic&lt;unsigned long&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_llong</code>
			</td>
			<td>
				<code>std::atomic&lt;long long&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_ullong</code>
			</td>
			<td>
				<code>std::atomic&lt;unsigned long long&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_char16_t</code>
			</td>
			<td>
				<code>std::atomic&lt;char16_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_char32_t</code>
			</td>
			<td>
				<code>std::atomic&lt;char32_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_wchar_t</code>
			</td>
			<td>
				<code>std::atomic&lt;wchar_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_int8_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::int8_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_uint8_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::uint8_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_int16_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::int16_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_uint16_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::uint16_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_int32_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::int32_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_uint32_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::uint32_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_int64_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::int64_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_uint64_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::uint64_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_int_least8_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::int_least8_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_uint_least8_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::uint_least8_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_int_least16_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::int_least16_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_uint_least16_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::uint_least16_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_int_least32_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::int_least32_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_uint_least32_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::uint_least32_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_int_least64_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::int_least64_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_uint_least64_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::uint_least64_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_int_fast8_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::int_fast8_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_uint_fast8_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::uint_fast8_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_int_fast16_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::int_fast16_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_uint_fast16_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::uint_fast16_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_int_fast32_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::int_fast32_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_uint_fast32_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::uint_fast32_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_int_fast64_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::int_fast64_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_uint_fast64_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::uint_fast64_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_intptr_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::intptr_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_uintptr_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::uintptr_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_size_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::size_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_ptrdiff_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::ptrdiff_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_intmax_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::intmax_t&gt;</code>‎
			</td>
		</tr>
<tr>
<td>
				<code>std::atomic_uintmax_t</code>
			</td>
			<td>
				<code>std::atomic&lt;std::uintmax_t&gt;</code>‎
			</td>
		</tr>
</tbody>
</table>
<p>
	هذا مثال بسيط على استخدام <code>std::atomic_int</code>:‎
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_45" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">       </span><span class="com">// std::cout</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;atomic&gt;</span><span class="pln">         </span><span class="com">// std::atomic, std::memory_order_relaxed</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;thread&gt;</span><span class="pln">         </span><span class="com">// std::thread</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">atomic_int foo</span><span class="pun">(</span><span class="lit">0</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> set_foo</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    foo</span><span class="pun">.</span><span class="pln">store</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">memory_order_relaxed</span><span class="pun">);</span><span class="pln"> </span><span class="com">// تعيين القيمة الذرية</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> print_foo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">do</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        x </span><span class="pun">=</span><span class="pln"> foo</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">memory_order_relaxed</span><span class="pun">);</span><span class="pln"> </span><span class="com">// الحصول على القيمة الذرّية</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"foo: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> x </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">thread first</span><span class="pun">(</span><span class="pln">print_foo</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">thread second</span><span class="pun">(</span><span class="pln">set_foo</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">);</span><span class="pln">
    first</span><span class="pun">.</span><span class="pln">join</span><span class="pun">();</span><span class="pln">
    </span><span class="com">//second.join();</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// foo: 10</span></pre>

<h2>
	std::variant: المتغايرات
</h2>

<h3>
	إنشاء مؤشرات للتوابع الزائفة (Create pseudo-method pointers)
</h3>

<p>
	يمكنك استخدام كائن متغَاير (Variant) للشطب الخفيف للنوع (light weight type erasure). انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_47" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> F </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> pseudo_method </span><span class="pun">{</span><span class="pln">
        F f</span><span class="pun">;</span><span class="pln">
        </span><span class="com">// C++17 السماح باستنتاج نوع الصنف في</span><span class="pln">
        pseudo_method</span><span class="pun">(</span><span class="pln">F </span><span class="pun">&amp;&amp;</span><span class="pln"> fin</span><span class="pun">):</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">fin</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
      </span><span class="com">// عامل بحث كوينج-&gt;* لا بأس بما أنه تابع زائف</span><span class="pln">
  </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Variant</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="com">// متغاير LHS  للتحقق من أنّ  SFINAE إضافة اختبار</span><span class="pln">
            </span><span class="kwd">friend</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="kwd">auto</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">-&gt;*(</span><span class="pln"> </span><span class="typ">Variant</span><span class="pun">&amp;&amp;</span><span class="pln"> var</span><span class="pun">,</span><span class="pln"> pseudo_method </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> method </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                </span><span class="com">// تعيد تعبير لامدا يعيد توجيه استدعاء دالة ما var-&gt;*method</span><span class="pln">
                </span><span class="com">// مما يجعلها تبدو كأنها تتصرف كمؤشّر تابع</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">[&amp;](</span><span class="kwd">auto</span><span class="pun">&amp;&amp;...</span><span class="pln">args</span><span class="pun">)-&gt;</span><span class="kwd">decltype</span><span class="pun">(</span><span class="kwd">auto</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                    </span><span class="com">// للحصول على نوع المتغاير visit استخدم</span><span class="pln">
                    </span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">visit</span><span class="pun">(</span><span class="pln">
                        </span><span class="pun">[&amp;](</span><span class="kwd">auto</span><span class="pun">&amp;&amp;</span><span class="pln"> self</span><span class="pun">)-&gt;</span><span class="kwd">decltype</span><span class="pun">(</span><span class="kwd">auto</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                            </span><span class="kwd">return</span><span class="pln"> method</span><span class="pun">.</span><span class="pln">f</span><span class="pun">(</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)(</span><span class="pln">self</span><span class="pun">),</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">args</span><span class="pun">)(</span><span class="pln">args</span><span class="pun">)...</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
                        </span><span class="pun">},</span><span class="pln">
                        std</span><span class="pun">::</span><span class="pln">forward </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Var</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var</span><span class="pun">)</span><span class="pln">
                 </span><span class="pun">);</span><span class="pln">
             </span><span class="pun">};</span><span class="pln">
         </span><span class="pun">}</span><span class="pln">
 </span><span class="pun">};</span></pre>

<p>
	يؤدي هذا إلى إنشاء نوع يزيد تحميل العامل <code>‎operator-&gt;*‎</code> بمتغاير <code>‎Variant‎</code> على الجانب الأيسر. في المثال التالي، سنستخدم استنتاج نوع الصنف الخاص بـ C++ 17 من أجل إيجاد وسيط القالب لـ <code>print</code>، يجب أن يكون <code>self</code> هو أول وسيط يأخذه تابع لامدا الزائف، ثم يأخذ بقية الوسائط ثم يستدعي الدالة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_49" style="">
<span class="pln">pseudo_method print </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[](</span><span class="kwd">auto</span><span class="pun">&amp;&amp;</span><span class="pln"> self</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">auto</span><span class="pun">&amp;&amp;...</span><span class="pln">args</span><span class="pun">)-&gt;</span><span class="kwd">decltype</span><span class="pun">(</span><span class="kwd">auto</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)(</span><span class="pln">self</span><span class="pun">).</span><span class="pln">print</span><span class="pun">(</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">args</span><span class="pun">)(</span><span class="pln">args</span><span class="pun">)...</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	والآن إن كان لدينا نوعان لكل منهما تابع <code>‎print‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_51" style="">
<span class="kwd">struct</span><span class="pln"> A </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> print</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ostream </span><span class="pun">&amp;</span><span class="pln"> os</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        os </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"A"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> B </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> print</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ostream </span><span class="pun">&amp;</span><span class="pln"> os</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        os </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"B"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	لاحظ أنّهما نوعان غير مترابطان، نستطيع تنفيذ ما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_53" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">variant</span><span class="pun">&lt;</span><span class="pln">A</span><span class="pun">,</span><span class="pln">B</span><span class="pun">&gt;</span><span class="pln"> var </span><span class="pun">=</span><span class="pln"> A</span><span class="pun">{};</span><span class="pln">
</span><span class="pun">(</span><span class="pln">var</span><span class="pun">-&gt;*</span><span class="pln">print</span><span class="pun">)(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">);</span></pre>

<p>
	سيتم إرسال الاستدعاء مباشرة إلى <code>‎A::print(std::cout)‎</code>، لكن لو هيأنا <code>‎var‎</code> باستخدام <code>‎B{}‎</code>، فسيتم إرساله إلى <code>‎B::print(std::cout)‎</code>.
</p>

<p>
	وإذا أنشأنا نوعًا جديدًا C …
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_55" style="">
<span class="kwd">struct</span><span class="pln"> C </span><span class="pun">{};</span></pre>

<p>
	… فسيكون لدينا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_57" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">variant</span><span class="pun">&lt;</span><span class="pln">A</span><span class="pun">,</span><span class="pln">B</span><span class="pun">,</span><span class="pln">C</span><span class="pun">&gt;</span><span class="pln"> var </span><span class="pun">=</span><span class="pln"> A</span><span class="pun">{};</span><span class="pln">
</span><span class="pun">(</span><span class="pln">var</span><span class="pun">-&gt;*</span><span class="pln">print</span><span class="pun">)(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">);</span></pre>

<p>
	ستفشل عملية التصريف، لأنه لا يوجد تابع <code>‎C.print(std::cout)‎</code>.
</p>

<p>
	سوف يسمح توسيع الشيفرة أعلاه باكتشاف واستخدام دوال <code>‎print‎</code>، ربّما باستخدام <code>‎if constexpr‎</code> ضمن التابع الزائف <code>‎print‎</code>.
</p>

<p>
	هذا <a data-ss1617022533="1" href="coliru.stacked-crooked.com/a/57f29d8406ad7b51" rel="">مثال حي</a> يستخدم <code>‎boost::variant‎</code> بدلاً من <code>‎std::variant‎</code>.
</p>

<h3>
	الاستخدامات الرئيسية للمتغايرات
</h3>

<p>
	تنشي الشيفرة التالية متغايرًا (اتحادًا موسومًا tagged union) يمكنه تخزين إمّا عدد صحيح (<code>‎int‎</code>) وإمّا سلسلة نصية<code>‎string‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_59" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">variant</span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&gt;</span><span class="pln"> var</span><span class="pun">;</span></pre>

<p>
	يمكننا تخزين أحد هذين النوعين في الكائن المتغاير:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_61" style="">
<span class="pln">var </span><span class="pun">=</span><span class="pln"> </span><span class="str">"hello"</span><span class="pln">s</span><span class="pun">;</span></pre>

<p>
	ويمكننا الوصول إلى مُحتوياته عبر <code>‎std::visit‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_64" style="">
<span class="com">// "hello\n" طباعة</span><span class="pln">
visit</span><span class="pun">(</span><span class="pln"> </span><span class="pun">[](</span><span class="kwd">auto</span><span class="pun">&amp;&amp;</span><span class="pln"> e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> e </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">},</span><span class="pln">
    var</span><span class="pun">);</span></pre>

<p>
	عن طريق تمرير دالّّة لامدا <a data-ss1617022533="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-16-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-%D8%A7%D9%84%D8%AA%D8%B9%D8%AF%D8%AF%D9%8A%D8%A9-%D8%A7%D9%84%D8%B4%D9%83%D9%84%D9%8A%D8%A9-polymorphism-%D9%81%D9%8A-cpp-r900/" rel="">متعددة الأشكال</a> أو كائن دالّّة مشابه، وإذا كنا متأكّدين من النوع، فيمكننا الحصول عليه على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_66" style="">
<span class="kwd">auto</span><span class="pln"> str </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">get</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&gt;(</span><span class="pln">var</span><span class="pun">);</span></pre>

<p>
	ولكن هذا سوف يرفع اعتراضًا إن أخطأنا تقدير النوع.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_68" style="">
<span class="kwd">auto</span><span class="pun">*</span><span class="pln"> str  </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">get_if</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&gt;(&amp;</span><span class="pln">var</span><span class="pun">);</span></pre>

<p>
	إن أخطأت التقدير فستُعاد القيمة <code>‎nullptr‎</code>.
</p>

<p>
	تضمن المُتغايرات عدم تخصيص ذاكرة ديناميكية، باستثناء تلك التي تُخصَّص من قبل أنواعها المُضمّنة، ولا يُخزَّن إلا نوع واحد فقط في المتغاير، ويرافقها في حالات نادرة رفع اعتراضات أثناء الإسناد وغياب إمكانية آمنة للتراجع يمكن أن يصبح المتغاير فارغًا.
</p>

<p>
	كما تتيح لك المُتغايرات تخزين قيم من عدّة أنواع في متغيّر واحد بأمان وكفاءة. فهي أساسًا اتحادات<code>‎union‎</code> ذكية وآمنة.
</p>

<h3>
	إنشاء متغاير
</h3>

<p>
	هذا لا يشمل المُخصِّصات (allocators).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_70" style="">
<span class="kwd">struct</span><span class="pln"> A </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> B </span><span class="pun">{</span><span class="pln"> B</span><span class="pun">()=</span><span class="kwd">default</span><span class="pun">;</span><span class="pln"> B</span><span class="pun">(</span><span class="pln">B </span><span class="kwd">const</span><span class="pun">&amp;)=</span><span class="kwd">default</span><span class="pun">;</span><span class="pln"> B</span><span class="pun">(</span><span class="typ">int</span><span class="pun">){};</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> C </span><span class="pun">{</span><span class="pln"> C</span><span class="pun">()=</span><span class="kwd">delete</span><span class="pun">;</span><span class="pln"> C</span><span class="pun">(</span><span class="typ">int</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{};</span><span class="pln"> C</span><span class="pun">(</span><span class="pln">C </span><span class="kwd">const</span><span class="pun">&amp;)=</span><span class="kwd">default</span><span class="pun">;</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> D </span><span class="pun">{</span><span class="pln"> D</span><span class="pun">(</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">initializer_list</span><span class="str">&lt;int&gt;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{};</span><span class="pln"> D</span><span class="pun">(</span><span class="pln">D </span><span class="kwd">const</span><span class="pun">&amp;)=</span><span class="kwd">default</span><span class="pun">;</span><span class="pln"> D</span><span class="pun">()=</span><span class="kwd">default</span><span class="pun">;</span><span class="pln"> </span><span class="pun">};</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">variant </span><span class="pun">&lt;</span><span class="pln"> A</span><span class="pun">,</span><span class="pln"> B </span><span class="pun">&gt;</span><span class="pln"> var_ab0</span><span class="pun">;</span><span class="pln"> </span><span class="com">//  A() يحتوي</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">variant </span><span class="pun">&lt;</span><span class="pln"> A</span><span class="pun">,</span><span class="pln"> B </span><span class="pun">&gt;</span><span class="pln"> var_ab1 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">7</span><span class="pun">;</span><span class="pln"> </span><span class="com">//  a B(7)  يحتوي</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">variant </span><span class="pun">&lt;</span><span class="pln"> A</span><span class="pun">,</span><span class="pln"> B </span><span class="pun">&gt;</span><span class="pln"> var_ab2 </span><span class="pun">=</span><span class="pln"> var_ab1</span><span class="pun">;</span><span class="pln"> </span><span class="com">//  a B(7)  يحتوي</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">variant </span><span class="pun">&lt;</span><span class="pln"> A</span><span class="pun">,</span><span class="pln"> B</span><span class="pun">,</span><span class="pln"> C </span><span class="pun">&gt;</span><span class="pln"> var_abc0 </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">in_place_type </span><span class="pun">&lt;</span><span class="pln"> C </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pln">
</span><span class="pun">};</span><span class="pln"> </span><span class="com">//  a C(7) يحتوي</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">variant </span><span class="pun">&lt;</span><span class="pln"> C </span><span class="pun">&gt;</span><span class="pln"> var_c0</span><span class="pun">;</span><span class="pln"> </span><span class="com">// C  لأجل ctor غير قانوني، لا توجد قيمة افتراضية لـ</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">variant</span><span class="pun">&lt;</span><span class="pln">A</span><span class="pun">,</span><span class="pln">D</span><span class="pun">&gt;</span><span class="pln"> var_ad0</span><span class="pun">(</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">in_place_type</span><span class="pun">&lt;</span><span class="pln">D</span><span class="pun">&gt;,</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="lit">3</span><span class="pun">,</span><span class="lit">3</span><span class="pun">,</span><span class="lit">4</span><span class="pun">}</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">//  D{1,3,3,4} يحتوي</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">variant </span><span class="pun">&lt;</span><span class="pln"> A</span><span class="pun">,</span><span class="pln"> D </span><span class="pun">&gt;</span><span class="pln"> var_ad1</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">in_place_index </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">//  A{} يحتوي</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">variant</span><span class="pun">&lt;</span><span class="pln">A</span><span class="pun">,</span><span class="pln">D</span><span class="pun">&gt;</span><span class="pln"> var_ad2</span><span class="pun">(</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">in_place_index</span><span class="pun">&lt;</span><span class="lit">1</span><span class="pun">&gt;,</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="lit">3</span><span class="pun">,</span><span class="lit">3</span><span class="pun">,</span><span class="lit">4</span><span class="pun">}</span><span class="pln"> </span><span class="pun">);</span><span class="pln">  </span><span class="com">// D{1,3,3,4} يحتوي</span></pre>

<h2>
	std::iomanip و std::any
</h2>

<h3>
	std::setprecision
</h3>

<p>
	عند استخدام <code>std::setprecision</code> في التعبير <code>‎out &lt;&lt; setprecision(n)‎</code> أو <code>‎in &gt;&gt; setprecision(n)‎</code>، فإنّها تضبط معامل الدقة (precision parameter) الخاصّ <a data-ss1617022533="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-11-%D8%AF%D8%AE%D9%84-%D9%88%D8%AE%D8%B1%D8%AC-%D8%A7%D9%84%D9%85%D9%84%D9%81%D8%A7%D8%AA-file-io-%D9%81%D9%8A-cpp-r895/" rel="">بمجرى</a> الخرج أو الدخل عند القيمة <code>n</code>.
</p>

<p>
	معامل هذه الدالّة يكون عددًا صحيحًا، ويمثل قيمة الدقة الجديدة. انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_72" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iomanip&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;cmath&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;limits&gt;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> pi </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">acos</span><span class="pun">(-</span><span class="lit">1.L</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"default precision (6): "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> pi </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln">
        </span><span class="str">"std::precision(10):    "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setprecision</span><span class="pun">(</span><span class="lit">10</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> pi </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln">
        </span><span class="str">"max precision:         "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">setprecision</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">numeric_limits </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">digits10 </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln">
        pi </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">//Output</span><span class="pln">
</span><span class="com">// 3.14159 :  في الدقة الافتراضية (6) يكون الناتج</span><span class="pln">
</span><span class="com">// std::precision(10):    3.141592654</span><span class="pln">
</span><span class="com">// 3.141592653589793239  :الدقة القصوى</span></pre>

<h3>
	std::setﬁll
</h3>

<p>
	عند استخدام <code>std::setﬁll</code> في تعبير <code>‎out &lt;&lt; setfill(c)‎</code>، فإنّها تُضبط محرف الملء (ﬁll character) الخاصّ بمجرى الخرج عند القيمة <code>‎c‎</code>.
</p>

<p>
	<strong>ملاحظة</strong>: يمكن الحصول على محرف الملء الحالي عبر الدالّة <code>‎std::ostream::fill‎</code>. مثال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_74" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iomanip&gt;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"default fill: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setw</span><span class="pun">(</span><span class="lit">10</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">42</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln">
        </span><span class="str">"setfill('*'): "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setfill</span><span class="pun">(</span><span class="str">'*'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">setw</span><span class="pun">(</span><span class="lit">10</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">42</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// 42  :الافتراضي</span><span class="pln">
</span><span class="com">// setfill('*'): ********42</span></pre>

<h3>
	std::setiosﬂags
</h3>

<p>
	عند استخدام <code>std::setiosﬂags</code> في التعبير <code>‎out &lt;&lt; setiosflags(mask)‎</code> أو <code>‎in &gt;&gt; setiosflags(mask)‎</code>، فإنّها تضبط كل رايات التنسيق (format ﬂags) الخاصّة بمجرى الخرج أو الدخل كما هو محدّد من قِبل القناع (mask).
</p>

<p>
	هذه قائمة بكل رايات <code>‎std::ios_base::fmtflags‎</code>:
</p>

<ul>
<li>
		<code>‎dec‎</code>: استخدام أساس عشري لدخل وخرج (I / O) الأعداد الصحيحة
	</li>
	<li>
		<code>‎oct‎</code>: استخدام أساس ثماني (octal base) لدخل وخرج الأعداد الصحيحة
	</li>
	<li>
		<code>‎hex‎</code>: استخدام أساس ست عشري (hexadecimal base) لدخل وخرج الأعداد الصحيحة
	</li>
	<li>
		<code>‎basefield‎</code> - <code>‎dec‎|‎oct‎|‎hex‎|‎0‎</code>: مفيدة لتقنيع (masking) العمليات
	</li>
	<li>
		<code>‎left‎</code>: التعديل الأيسر (إضافة محارف الملْء إلى اليمين)
	</li>
	<li>
		<code>‎right‎</code>: التعديل الأيمن (إضافة محارف الملء إلى اليسار)
	</li>
	<li>
		<code>‎internal‎</code>: التعديل الداخلي (إضافة محارف الملء إلى نقطة معيّنة في الداخل)
	</li>
	<li>
		<code>adjustfield</code> - <code>left|right|internal</code> : مفيدة لتقنيع العمليات.
	</li>
	<li>
		<code>‎scientific‎</code>: توليد الأنواع العددية العشرية باستخدام الصيغة العلمية، أو الصيغة الثمانية (hex notation) في حال اقترنت بـ ﬁxed.
	</li>
	<li>
		<code>‎fixed‎</code>: توليد الأنواع العددية العشرية باستخدام الصيغة الثابتة (ﬁxed notation)، أو الصيغة الثمانية (hex notation) في حال اقترنت بـ scientific. *<code>‎floatfield‎</code> - <code>‎scientific‎|‎fixed‎|(scientific‎|‎fixed‎)|‎0‎</code>: مفيدة لتقنيع لعمليات
	</li>
	<li>
		<code>‎boolalpha‎</code>: إدراج واستخراج نوع منطقي وفق تنسيق أبجدي رقمي
	</li>
	<li>
		<code>‎showbase‎</code>: إنشاء سابقة (preﬁx) تشير إلى الأساس الرقمي لخرج الأعداد الصحيحة، وتتطلّب إشارة إلى العُملة في حال الدخل والخرج الماليّ.
	</li>
	<li>
		<code>‎showpoint‎</code>: إنشاء محرفَ الفاصلة العشرية (decimal-point character) دون قيد أو شرط لخرج الأعداد العشرية
	</li>
	<li>
		<code>‎showpos‎</code>: توليد المحرف <code>‎+‎</code> للأعداد غير السالبة
	</li>
	<li>
		<code>‎skipws‎</code>: تخطي المسافات البيضاء الموجودة في البداية قبل عمليات الإدخال
	</li>
	<li>
		<code>‎unitbuf‎</code>: نقل (flush) الناتج بعد كل عملية خرج
	</li>
	<li>
		<code>‎uppercase‎</code>: استبدال بعض الأحرف الصغيرة بالأحرف الكبيرة المقابلة لها في بعض مخرجات عمليات الإخراج.
	</li>
</ul>
<p>
	أمثلة على المعدِّلات:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_76" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;string&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="str">&lt;iomanip&gt;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> l_iTemp </span><span class="pun">=</span><span class="pln"> </span><span class="lit">47</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">resetiosflags</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ios_base</span><span class="pun">::</span><span class="pln">basefield</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setiosflags</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ios_base</span><span class="pun">::</span><span class="pln">oct</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> l_iTemp </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// ==&gt; 57</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">resetiosflags</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ios_base</span><span class="pun">::</span><span class="pln">basefield</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setiosflags</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ios_base</span><span class="pun">::</span><span class="pln">hex</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> l_iTemp </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// ==&gt; 2f</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setiosflags</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ios_base</span><span class="pun">::</span><span class="pln">uppercase</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> l_iTemp </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// ==&gt; 2F</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setfill</span><span class="pun">(</span><span class="str">'0'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setw</span><span class="pun">(</span><span class="lit">12</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">resetiosflags</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ios_base</span><span class="pun">::</span><span class="pln">uppercase</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setiosflags</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ios_base</span><span class="pun">::</span><span class="pln">right</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> l_iTemp </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// ==&gt; 00000000002f</span><span class="pln">

    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">resetiosflags</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ios_base</span><span class="pun">::</span><span class="pln">basefield </span><span class="pun">|</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">ios_base</span><span class="pun">::</span><span class="pln">adjustfield</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setfill</span><span class="pun">(</span><span class="str">'.'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setw</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setiosflags</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ios_base</span><span class="pun">::</span><span class="pln">left</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> l_iTemp </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// ==&gt; 47........</span><span class="pln">

    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">resetiosflags</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ios_base</span><span class="pun">::</span><span class="pln">adjustfield</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setfill</span><span class="pun">(</span><span class="str">'#'</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setiosflags</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ios_base</span><span class="pun">::</span><span class="pln">internal </span><span class="pun">|</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">ios_base</span><span class="pun">::</span><span class="pln">showpos</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setw</span><span class="pun">(</span><span class="lit">10</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> l_iTemp </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// ==&gt; +#######47</span><span class="pln">

    </span><span class="kwd">double</span><span class="pln"> l_dTemp </span><span class="pun">=</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1.2</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">double</span><span class="pln"> pi </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3.14159265359</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> pi </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"    "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> l_dTemp </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// ==&gt; +3.14159   -1.2</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setiosflags</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ios_base</span><span class="pun">::</span><span class="pln">showpoint</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> l_dTemp </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// ==&gt; -1.20000</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> setiosflags</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ios_base</span><span class="pun">::</span><span class="pln">scientific</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> pi </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// ==&gt; +3.141593e+00</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">resetiosflags</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ios_base</span><span class="pun">::</span><span class="pln">floatfield</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> setiosflags</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ios_base</span><span class="pun">::</span><span class="pln">fixed</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> pi </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// ==&gt; +3.141593</span><span class="pln">
    </span><span class="kwd">bool</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setiosflags</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ios_base</span><span class="pun">::</span><span class="pln">unitbuf </span><span class="pun">|</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">ios_base</span><span class="pun">::</span><span class="pln">boolalpha</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// ==&gt; true</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	std::setw
</h3>

<p>
	انظر المثال التالي حيث يطبع السطر الثاني <code>val</code> في أقصى يسار شاشة الخرج، بينما يطبعها السطر الثالث في حقل إخراج طوله 10 بدءًا من النهاية اليمنى للحقل:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_78" style="">
<span class="typ">int</span><span class="pln"> val </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> val </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setw</span><span class="pun">(</span><span class="lit">10</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> val </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></pre>

<p>
	يكون الخرج ما يلي:
</p>

<pre class="ipsCode">
10
10
1234567890
</pre>

<p>
	(السطر الأخير موجود للمساعدة على رؤية مواضع الأحرف).
</p>

<p>
	عندما نحتاج إلى أن يكون الخرج مُنسّقًا بتنسيق معيّن، فقد نحتاج إلى ضبط عرض الحقل، ويمكن القيام بذلك باستخدام <code>std::setw</code> و <code>std::iomanip</code>. توضّح الشيفرة التالية صيغة <code>‎std::setw‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_80" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">setw</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> n</span><span class="pun">)</span></pre>

<p>
	يمثّل <code>n</code> في هذا المثال طول حقل الخرج الذي سيُعيَّن.
</p>

<h3>
	std::any
</h3>

<p>
	يوضح المثال التالي كيفية استخدام <code>std::any</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_82" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">any an_object</span><span class="pun">{</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">(</span><span class="str">"hello world"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">an_object</span><span class="pun">.</span><span class="pln">has_value</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">any_cast</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&gt;(</span><span class="pln">an_object</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">any_cast</span><span class="str">&lt;int&gt;</span><span class="pun">(</span><span class="pln">an_object</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">catch</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">bad_any_cast</span><span class="pun">&amp;)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Wrong type\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">any_cast</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&amp;&gt;(</span><span class="pln">an_object</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"42"</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">any_cast</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&gt;(</span><span class="pln">an_object</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span></pre>

<p>
	المخرجات الناتجة:
</p>

<pre class="ipsCode">
hello world
Wrong type
42
</pre>

<h2>
	std::set و std::multiset: المجموعات والمجموعات المتعددة
</h2>

<p>
	تمثّل المجموعات "<code>‎set‎</code>" نوعًا من الحاويات عناصرها مُرتّبة وغير مكرّرة، أمّا المجموعات المتعدّدة <code>‎multiset‎</code>، فتشبه المجموعات العادية، لكن العناصر المتعددة تكون لها نفس القيمة.
</p>

<h3>
	تغيير الترتيب الافتراضي لمجموعة ما
</h3>

<p>
	لدى الصّنفين <code>‎set‎</code> و <code>‎multiset‎</code> توابع مقارنة افتراضية، ولكن قد تحتاج أحيانًا في بعض الحالات إلى <a data-ss1617022533="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-22-%D8%A7%D9%84%D8%AA%D8%AD%D9%85%D9%8A%D9%84-%D8%A7%D9%84%D8%B2%D8%A7%D8%A6%D8%AF-overloading-%D8%AA%D8%AD%D9%84%D9%8A%D9%84%D9%87-%D9%88%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D9%87-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D9%81%D9%8A-cpp-r934/" rel="">زيادة تحميلها</a>. فمثلًا، لنفترض أنّنا نخزّن سلاسل نصية في مجموعة ما، ونحن نعلم أن تلك السلاسل تحتوي على قيم رقمية فقط. يكون الترتيب الافتراضي قائمًا على المقارنة الأبجدية للسلاسل النصّية، وعليه فلن يتطابق الترتيب مع الترتيب الرقمي. وإن أردت ترتيبها ترتيبًا عدديًا فستحتاج إلى كائن دالّي (functor) لزيادة تحميل تابع الموازنة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_84" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;set&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;stdlib.h&gt;</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> custom_compare final </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">bool</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">()(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&amp;</span><span class="pln"> left</span><span class="pun">,</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&amp;</span><span class="pln"> right</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> nLeft </span><span class="pun">=</span><span class="pln"> atoi</span><span class="pun">(</span><span class="pln">left</span><span class="pun">.</span><span class="pln">c_str</span><span class="pun">());</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> nRight </span><span class="pun">=</span><span class="pln"> atoi</span><span class="pun">(</span><span class="pln">right</span><span class="pun">.</span><span class="pln">c_str</span><span class="pun">());</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> nLeft </span><span class="pun">&lt;</span><span class="pln"> nRight</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
 std</span><span class="pun">::</span><span class="typ">set</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&gt;</span><span class="pln"> sut</span><span class="pun">({</span><span class="str">"1"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"2"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"5"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"23"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"6"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"290"</span><span class="pun">});</span><span class="pln">

    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"### Default sort on std::set&lt;std::string&gt; :"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> data</span><span class="pun">:</span><span class="pln"> sut</span><span class="pun">)</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> data </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">

    std</span><span class="pun">::</span><span class="typ">set</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> custom_compare</span><span class="pun">&gt;</span><span class="pln"> sut_custom</span><span class="pun">({</span><span class="str">"1"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"2"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"5"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"23"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"6"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"290"</span><span class="pun">},</span><span class="pln">
custom_compare </span><span class="pun">{});</span><span class="pln"> 

    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"### Custom sort on set :"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> data</span><span class="pun">:</span><span class="pln"> sut_custom</span><span class="pun">)</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> data </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">auto</span><span class="pln"> compare_via_lambda </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[](</span><span class="kwd">auto</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln">lhs</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln">rhs</span><span class="pun">){</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> lhs </span><span class="pun">&gt;</span><span class="pln"> rhs</span><span class="pun">;</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
 </span><span class="kwd">using</span><span class="pln"> set_via_lambda </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">set</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">compare_via_lambda</span><span class="pun">)&gt;;</span><span class="pln">
 set_via_lambda sut_reverse_via_lambda</span><span class="pun">({</span><span class="str">"1"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"2"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"5"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"23"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"6"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"290"</span><span class="pun">},</span><span class="pln">
compare_via_lambda</span><span class="pun">);</span><span class="pln">

    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"### Lambda sort on set :"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> data</span><span class="pun">:</span><span class="pln"> sut_reverse_via_lambda</span><span class="pun">)</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> data </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يكون الخرج ما يلي:
</p>

<pre class="ipsCode">
### Default sort on std::set&lt;std::string&gt; :
1
2
23
290
5
6
### Custom sort on set :
1
2
5
6
23
290
### Lambda sort on set :
6
5
290
23
2
1
</pre>

<p>
	في المثال أعلاه، يمكن استخدام ثلاث طرق مختلفة لإضافة عمليات مقارنة إلى المجموعات "<code>‎std::set‎</code>"، ولكلّ منها فوائدها.
</p>

<h4>
	الترتيب الافتراضي
</h4>

<p>
	يستخدم الترتيب الافتراضي عامل المقارنة الخاصّ بالمفتاح (الوسيط الأول للقالب)، وغالبًا ما يكون المفتاح إعدادًا افتراضيًا مناسبًا للدالّة <code>‎std::less&lt;T&gt;‎</code>. وستستخدم هذه الدالة العامل <code>‎operator&lt;‎</code> الخاص بالكائن ما لم تكن قد خُصِّصت، هذا مفيد خاصّة عندما تحاول شيفرة أخرى استخدام ترتيب معيّن، إذ يجعل الشيفرة متناسقة.
</p>

<p>
	ستؤدي كتابة الشيفرة بهذه الطريقة إلى تسهيل تحديثها عندما تكون تغييرات المفتاح جزءًا من واجهة برمجية (<abbr title="Application Programming Interface | واجهة برمجية">API</abbr>)، فمثلًا إن كان لدينا صنف يحتوي على عضوين، وسيتغيّر إلى صنف يحتوي 3 أعضاء، فستُحدَّث جميع النُّسخ عبر تحديث <code>‎operator&lt;‎</code> الخاص بالصنف. وكما تتوقع، فإن استخدام التصنيف الافتراضي كخيار افتراضي منطقي ومقبول.
</p>

<h4>
	الترتيب المُخصّص
</h4>

<p>
	يمكن إضافة ترتيب مُخصّص عبر كائن له عامل مقارنة عندما لا تكون المقارنة الافتراضية مناسبة، كما في المثال أعلاه إذ تشير السلاسل النصيّة إلى أعداد صحيحة.
</p>

<p>
	يمكن أيضًا استخدام الترتيب المُخصّص في حال كنت ترغب في مقارنة المؤشّرات (الذكية) استنادًا إلى الكائن الذي تشير إليه، أو في حال كنت تحتاج إلى قيود خاصّة في عملية المقارنة، كمقارنة الأزواج <code>‎std::pair‎</code> بقيمة العنصر الأول <code>‎first‎</code> فقط.
</p>

<p>
	يجب أن تحرص على أن يكون الترتيب مستقرًّا (stable sorting) عند إنشاء عامل مقارنة، أي أنّ نتيجة عامل المقارنة بعد الإدراج يجب ألا تتغيّر، وإلا فهذا يعني أنّ السلوك غير محدّد. لذلك احرص على ألّا يستخدم عامل المقارنة إلّا البيانات الثابتة (الأعضاء، الدوالّ الثابتة، …).
</p>

<p>
	وستصادف غالبًا -كما في المثال أعلاه- أصنافًا بدون عوامل مقارنة، وينتج عن هذا منشئاتٌ افتراضية ومنشئاتُ نسخ (copy constructors)، ويسمح لك المُنشئ الافتراضي بحذف النسخة في وقت الإنشاء، كما أنّ منشئ النسخ ضروريّ لأنّ المجموعة تأخذ نسخة من مُعامل المقارنة.
</p>

<h4>
	الترتيب عبر تعابير لامدا
</h4>

<p>
	تعابير لامدا هي طريقة مختصرة لكتابة الدوالّ، وتتيح لنا كتابة امل المقارنة في سطور قليلة مما يسهل قراءة الشيفرة الكلّية.
</p>

<p>
	ما يعيب استخدام تعابير لامدا هو أنّه سيكون لكلّ واحد منها نوع محدّد في وقت التصريف، لذلك سيكون التعبير <code>‎decltype(lambda)‎</code> مختلفًا في كل تُصرَّف نفس وحدة التصريف (ملف cpp) عند وجود أكثر من وحدة تصريف تكون مُدرجة في ملفات الترويسة، ولهذا يوصى باستخدام كائنات الدوالّ كعوامل مقارنة عند استخدامها داخل ملفات الترويسة.
</p>

<p>
	سترى هذا النوع من الإنشاء غالبًا عند استخدام مجموعة "<code>‎std::set‎</code>" ضمن النطاق المحلي للدالّة. في حين يُفضَّل استعمال كائن دالّة عند استخدامه كوسيط لدالّة أو كعضو في صنف.
</p>

<h4>
	خيارات الترتيب الأخرى
</h4>

<p>
	نظرًا لأنّ عامل المقارنة الخاصّ بالمجموعات <code>‎std::set‎</code> عبارة عن وسيط قالب، فيمكن استخدام جميع الكائنات القابلة للاستدعاء كعوامل مقارنة، وما الأمثلة أعلاه إلا حالات خاصّة وحسب، ولا توجد قيود على هذه الكائنات القابلة للاستدعاء إلا ما يلي:
</p>

<ul>
<li>
		يجب أن تكون نسخة قابلة للإنشاء النّسخي (copy constructable)
	</li>
	<li>
		ويجب أن تكون قابلة للاستدعاء مع وسيطين من نوع المفتاح نفسه (التحويلات الضمنية مسموح بها رغم عدم استحسانها، لأنها قد تضرّ بالأداء).
	</li>
</ul>
<h3>
	حذف قيم من مجموعة
</h3>

<p>
	إذا كنت تريد إفراغ المجموعة أو المجموعة المتعدّدة من كل عناصرها، فيمكنك استخدام <code>‎clear‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_86" style="">
<span class="pln"> std</span><span class="pun">::</span><span class="typ">set</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> sut</span><span class="pun">;</span><span class="pln">
sut</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln">
sut</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">15</span><span class="pun">);</span><span class="pln">
sut</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">22</span><span class="pun">);</span><span class="pln">
sut</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">3</span><span class="pun">);</span><span class="pln">
sut</span><span class="pun">.</span><span class="pln">clear</span><span class="pun">();</span><span class="pln"> </span><span class="com">// يساوي 0 sut  حجم</span></pre>

<p>
	ثم يمكنك استخدام التابع <code>‎erase‎</code> الذي يوفّر بعض الوظائف التي تشبه عملية الإدراج:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_88" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">set</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> sut</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">set</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="typ">iterator</span><span class="pln"> it</span><span class="pun">;</span><span class="pln">

sut</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln">
sut</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">15</span><span class="pun">);</span><span class="pln">
sut</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">22</span><span class="pun">);</span><span class="pln">
sut</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">3</span><span class="pun">);</span><span class="pln">
sut</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">30</span><span class="pun">);</span><span class="pln">
sut</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">33</span><span class="pun">);</span><span class="pln">
sut</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">45</span><span class="pun">);</span><span class="pln">

</span><span class="com">// الحذف البسيط</span><span class="pln">
sut</span><span class="pun">.</span><span class="pln">erase</span><span class="pun">(</span><span class="lit">3</span><span class="pun">);</span><span class="pln">

</span><span class="com">// استخدام مكرّر</span><span class="pln">
it </span><span class="pun">=</span><span class="pln"> sut</span><span class="pun">.</span><span class="pln">find</span><span class="pun">(</span><span class="lit">22</span><span class="pun">);</span><span class="pln">
sut</span><span class="pun">.</span><span class="pln">erase</span><span class="pun">(</span><span class="pln">it</span><span class="pun">);</span><span class="pln">

</span><span class="com">// حذف مجال من القيم</span><span class="pln">
it </span><span class="pun">=</span><span class="pln"> sut</span><span class="pun">.</span><span class="pln">find</span><span class="pun">(</span><span class="lit">33</span><span class="pun">);</span><span class="pln">
sut</span><span class="pun">.</span><span class="pln">erase</span><span class="pun">(</span><span class="pln">it</span><span class="pun">,</span><span class="pln"> sut</span><span class="pun">.</span><span class="pln">end</span><span class="pun">());</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Set under test contains:"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">it </span><span class="pun">=</span><span class="pln"> sut</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">();</span><span class="pln"> it </span><span class="pun">!=</span><span class="pln"> sut</span><span class="pun">.</span><span class="pln">end</span><span class="pun">();</span><span class="pln"> </span><span class="pun">++</span><span class="pln">it</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> it </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الخرج سيكون:
</p>

<pre class="ipsCode">
Set under test contains:



10

15

30
</pre>

<p>
	تنطبق كلّ هذه التوابع أيضًا على المجموعات المتعدّدة <code>‎multiset‎</code>، يرجى ملاحظة أنّه في حال طلبت حذف عنصر من مجموعة متعدّدة <code>‎multiset‎</code> وكان ذلك العنصر مُكرَّرًا، فستُحذَف جميع العناصر التي تساوي ذلك العنصر.
</p>

<h3>
	إدراج قيم في مجموعة
</h3>

<p>
	هناك ثلاث طرق لإدراج العناصر في المجموعات.
</p>

<ol>
<li>
		إدراج بسيط للقيمة باستخدام التابع <code>insert</code> الذي يعيد زوجًا، ممّا يسمح للمُستدعي بالتحقق مما إذا كان الإدراج قد تمّ أم لا.
	</li>
	<li>
		يمكن الإدراج بإعطاء تلميح عن الموضع الذي ستُدرج فيه القيمة، والهدف من ذلك هو تحسين وقت الإدراج، لكن المشكلة أنّنا لا نعرف دائمًا الموضع الذي يجب أن تُدرج فيه القيمة. <strong>انتبه في هذه الحالة لأن طريقة إعطاء التلميح تختلف بحسب إصدارات المصرّفات</strong>.
	</li>
	<li>
		أخيرًا، يمكنك إدراج عدة قيم عن طريق إعطاء مؤشّر للبداية (مُضمّن) والنهاية (غير مُضمّن).
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_90" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;set&gt;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">set</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> sut</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">set</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="typ">iterator</span><span class="pln"> it</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">pair </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">set</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="typ">iterator</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> ret</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// إدراج بسيط</span><span class="pln">
    sut</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">7</span><span class="pun">);</span><span class="pln">
    sut</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">5</span><span class="pun">);</span><span class="pln">
    sut</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">12</span><span class="pun">);</span><span class="pln">

    ret </span><span class="pun">=</span><span class="pln"> sut</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">23</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">ret</span><span class="pun">.</span><span class="pln">second </span><span class="pun">==</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">)</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"# 23 has been inserted!"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">

    ret </span><span class="pun">=</span><span class="pln"> sut</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">23</span><span class="pun">);</span><span class="pln"> </span><span class="com">// بما أنها مجموعة، والعدد 23 موجودا سلفا فيها، فستفشل عملية الإدراج</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">ret</span><span class="pun">.</span><span class="pln">second </span><span class="pun">==</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">)</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"# 23 already present in set!"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// إدراج مع تلميح لتسريع الأداء</span><span class="pln">
    it </span><span class="pun">=</span><span class="pln"> sut</span><span class="pun">.</span><span class="pln">end</span><span class="pun">();</span><span class="pln">
    </span><span class="com">// وما بعده C++11 هذه الحالة محسَّنة في</span><span class="pln">
    </span><span class="com">// بالنسبة للإصدارات السابقة، يمكن التأشير إلى العنصر الذي يسبق موضع الإدراج</span><span class="pln">
    sut</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">it</span><span class="pun">,</span><span class="pln"> </span><span class="lit">30</span><span class="pun">);</span><span class="pln">
    </span><span class="com">// إدراج مجال من القيم</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">set</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> sut2</span><span class="pun">;</span><span class="pln">
    sut2</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">20</span><span class="pun">);</span><span class="pln">
    sut2</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">30</span><span class="pun">);</span><span class="pln">
    sut2</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">45</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">set</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="typ">iterator</span><span class="pln"> itStart </span><span class="pun">=</span><span class="pln"> sut2</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">();</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">set</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="typ">iterator</span><span class="pln"> itEnd </span><span class="pun">=</span><span class="pln"> sut2</span><span class="pun">.</span><span class="pln">end</span><span class="pun">();</span><span class="pln">

    sut</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">itStart</span><span class="pun">,</span><span class="pln"> itEnd</span><span class="pun">);</span><span class="pln"> </span><span class="com">// يُستثنى المكرر الثاني من الإدراج</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Set under test contains:"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">it </span><span class="pun">=</span><span class="pln"> sut</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">();</span><span class="pln"> it </span><span class="pun">!=</span><span class="pln"> sut</span><span class="pun">.</span><span class="pln">end</span><span class="pun">();</span><span class="pln"> </span><span class="pun">++</span><span class="pln">it</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> it </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	سينتج لنا الخرج التالي:
</p>

<pre class="ipsCode">
# 23 has been inserted!
# 23 already present in set!
Set under test contains:
5
7
12
20
23
30
45
</pre>

<h3>
	إدراج القيم في مجموعة متعددة
</h3>

<p>
	جميع طرق الإدراج الخاصّة بالمجموعات تنطبق أيضًا على المجموعات المتعدّدة، لكن هناك خيار آخر، وهو تمرير قائمة تهيئة initializer_list:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_92" style="">
<span class="kwd">auto</span><span class="pln"> il </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="lit">7</span><span class="pun">,</span><span class="pln">
    </span><span class="lit">5</span><span class="pun">,</span><span class="pln">
    </span><span class="lit">12</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">multiset</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> msut</span><span class="pun">;</span><span class="pln">
msut</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">il</span><span class="pun">);</span></pre>

<h3>
	البحث عن القيم في المجموعات والمجموعات المتعدّدة
</h3>

<p>
	هناك عدّة طرق للبحث عن قيمة معيّنة في مجموعة <code>‎std::set‎</code> أو مجموعة متعدّدة <code>‎std::multiset‎</code>، وللحصول على <a data-ss1617022533="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-8-%D8%A7%D9%84%D9%85%D9%83%D8%B1%D8%A7%D8%B1%D8%A7%D8%AA-iterators-%D9%81%D9%8A-cpp-r892/" rel="">مُكرِّر</a> يشير إلى موضع أوّل ظهور لمفتاح مُعيّن، يمكن استخدام الدالّة <code>‎find()‎</code> التي تعيد <code>‎end()‎</code> إذا لم يكن المفتاح موجودًا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_94" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">set</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> sut</span><span class="pun">;</span><span class="pln">
sut</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln">
sut</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">15</span><span class="pun">);</span><span class="pln">
sut</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">22</span><span class="pun">);</span><span class="pln">
sut</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">3</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 3, 10, 15, 22 </span><span class="pln">

</span><span class="kwd">auto</span><span class="pln"> itS </span><span class="pun">=</span><span class="pln"> sut</span><span class="pun">.</span><span class="pln">find</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln"> </span><span class="com">// *itS == 10 القيمة موجودة، لذا</span><span class="pln">
itS </span><span class="pun">=</span><span class="pln"> sut</span><span class="pun">.</span><span class="pln">find</span><span class="pun">(</span><span class="lit">555</span><span class="pun">);</span><span class="pln"> </span><span class="com">// itS == sut.end() لم يُعثَر على القيمة، لذا</span><span class="pln">

std</span><span class="pun">::</span><span class="typ">multiset</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> msut</span><span class="pun">;</span><span class="pln">
sut</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln">
sut</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">15</span><span class="pun">);</span><span class="pln">
sut</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">22</span><span class="pun">);</span><span class="pln">
sut</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">15</span><span class="pun">);</span><span class="pln">
sut</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">3</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 3, 10, 15, 15, 22 </span><span class="pln">

</span><span class="kwd">auto</span><span class="pln"> itMS </span><span class="pun">=</span><span class="pln"> msut</span><span class="pun">.</span><span class="pln">find</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span></pre>

<p>
	الطريقة الأخرى هي استخدام الدالّة <code>‎count()‎</code>، والتي تحسُب عدد القيم المطابقة التي عُثِر عليها في المجموعة أو المجموعة المتعدّدة (في حالة المجموعات، ستكون القيمة المُعادة إمّا 0 أو 1).
</p>

<p>
	باستخدام نفس القيم المذكورة أعلاه، سيكون لدينا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_96" style="">
<span class="typ">int</span><span class="pln"> result </span><span class="pun">=</span><span class="pln"> sut</span><span class="pun">.</span><span class="pln">count</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 1</span><span class="pln">
result </span><span class="pun">=</span><span class="pln"> sut</span><span class="pun">.</span><span class="pln">count</span><span class="pun">(</span><span class="lit">555</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 0</span><span class="pln">

result </span><span class="pun">=</span><span class="pln"> msut</span><span class="pun">.</span><span class="pln">count</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 1</span><span class="pln">
result </span><span class="pun">=</span><span class="pln"> msut</span><span class="pun">.</span><span class="pln">count</span><span class="pun">(</span><span class="lit">15</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 2</span></pre>

<p>
	في حالة المجموعات المتعدّدة، يمكن أن تكون هناك عدّة عناصر لها نفس القيمة، وللحصول على مجالٍ (range) يمثّل تلك العناصر يمكن استخدام الدالّة <code>‎equal_range()‎</code> التي تُعيد زوجًا يتألّف من مُكرّر الحدّ الأدنى (مُضمّن) ومُكرّر الحدّ الأعلى (غير مضمَن) على التوالي. وإذا لم يكن المفتاح موجودًا فسيشير كلا المُكرِّران إلى أقرب قيمة عليا وفق تابع المقارنة المُستخدم لترتيب المجموعة المتعدّدة المُعطاة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_98" style="">
<span class="kwd">auto</span><span class="pln"> eqr </span><span class="pun">=</span><span class="pln"> msut</span><span class="pun">.</span><span class="pln">equal_range</span><span class="pun">(</span><span class="lit">15</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> st </span><span class="pun">=</span><span class="pln"> eqr</span><span class="pun">.</span><span class="pln">first</span><span class="pun">;</span><span class="pln"> </span><span class="com">//  '15' يشير إلى العنصر الأول</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> en </span><span class="pun">=</span><span class="pln"> eqr</span><span class="pun">.</span><span class="pln">second</span><span class="pun">;</span><span class="pln"> </span><span class="com">// '22' يشير إلى العنصر</span><span class="pln">
eqr </span><span class="pun">=</span><span class="pln"> msut</span><span class="pun">.</span><span class="pln">equal_range</span><span class="pun">(</span><span class="lit">9</span><span class="pun">);</span><span class="pln"> </span><span class="com">//  '10' يشيران إلى  eqr.second و eqr.first كل من</span></pre>

<h2>
	std::integer_sequence: تسلسلات الأعداد الصحيحة
</h2>

<p>
	يمثّل قالب الصنف <code>‎std::integer_sequence&lt;Type, Values...&gt;‎</code> سلسلة من القيم العددية الصحيحة من نوع <code>‎Type‎</code>، حيث <code>‎Type‎</code> هو أحد أنواع الأعداد الصحيحة المُضمّنة.
</p>

<p>
	تُستخدم هذه التسلسلات عند تنفيذ قوالب الأصناف أو الدوالّ التي تحتاج إلى الوصول الموضعي (positional access)، وتحتوي المكتبة القياسية أيضًا على أنواع مصنَعيّة (factory types) تنشئ تسلسلات تصاعدية من الأعداد الصحيحة انطلاقًا من عدد العناصر المُراد.
</p>

<h3>
	تحويل صفّ <code>std::tuple&lt;T...&gt;‎</code> إلى معاملات دالّة
</h3>

<p>
	يمكن استخدام صفّ <code>‎std::tuple&lt;T...&gt;‎</code> لتمرير عدّة قيم إلى دالّة، فمثلًا يمكن استخدامه لتخزين سلسلة من المعاملات على شكل صف انتظار (queue)، ويجب تحويل عناصر هذه الصفوف عند معالجتها إلى وسائط استدعاء للدالة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_100" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;array&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;string&gt;</span><span class="pln">
include </span><span class="str">&lt;tuple&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;utility&gt;</span><span class="pln">

 </span><span class="com">// ----------------------------------------------------------------------------</span><span class="pln">
</span><span class="com">// الدوالّ المراد استدعاؤها</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string
    </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> s</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"f("</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> i </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> s </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">")\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> d</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string
    </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> s</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"f("</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> i </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> d </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> s </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">")\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">char</span><span class="pln"> c</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> d</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string
    </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> s</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"f("</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> c </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> i </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> d </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> s </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">")\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> j</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> k</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"f("</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> i </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> j </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> k </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">")\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// ----------------------------------------------------------------------------</span><span class="pln">
</span><span class="com">// الدالّة الفعلية التي توسّع الصف</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">Tuple</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pun">...</span><span class="pln">I </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> process</span><span class="pun">(</span><span class="typ">Tuple</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> tuple</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">index_sequence </span><span class="pun">&lt;</span><span class="pln"> I</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        f</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">get </span><span class="pun">&lt;</span><span class="pln"> I </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">tuple</span><span class="pun">)...);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="com">// الواجهة المراد استدعاؤها، للأسف يجب أن تُرسل إلى دالّة أخرى لاستخلاص سلسلة الفهارس المُنشأة</span><span class="pln">
</span><span class="com">// std::make_index_sequence&lt;N&gt; من</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">Tuple</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> process</span><span class="pun">(</span><span class="typ">Tuple</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> tuple</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        process</span><span class="pun">(</span><span class="pln">tuple</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_index_sequence </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">tuple_size </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Tuple</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">value </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">());</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="com">// ----------------------------------------------------------------------------</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    process</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">make_tuple</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3.14</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">(</span><span class="str">"foo"</span><span class="pun">)));</span><span class="pln">
    process</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">make_tuple</span><span class="pun">(</span><span class="str">'a'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2.71</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">(</span><span class="str">"bar"</span><span class="pun">)));</span><span class="pln">
    process</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">(</span><span class="str">"pair"</span><span class="pun">)));</span><span class="pln">
    process</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">array </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="lit">1</span><span class="pun">,</span><span class="pln">
        </span><span class="lit">2</span><span class="pun">,</span><span class="pln">
        </span><span class="lit">3</span><span class="pln">
    </span><span class="pun">});</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	طالما كان الصنف يدعم <code>‎std::get&lt;I&gt;(object)‎</code> و <code>‎std::tuple_size&lt;T&gt;::value‎</code>، فيمكن توسيعه باستخدام الدالّة <code>‎process()‎</code> أعلاه، إذ أنّ الدالّة نفسها مستقلّة تمامًا عن عدد الوسائط.
</p>

<h3>
	إنشاء حزمة مُعاملات مُكوّنة من أعداد صحيحة
</h3>

<p>
	تُستخدَم <code>std::integer_sequence</code> لتخزين سلسلة من الأعداد الصحيحة التي يمكن تحويلها إلى حُزمة معاملات، وفائدتها الرئيسيّة هو إمكانية إنشاء قوالب الأصناف المصنعيّة التي ستنشئ تلك التسلسلات:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_102" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;initializer_list&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;utility&gt;</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> T</span><span class="pun">...</span><span class="pln">I </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> print_sequence</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">integer_sequence </span><span class="pun">&lt;</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> I</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">initializer_list </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">bool</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> I </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">' '</span><span class="pun">)...</span><span class="pln">
        </span><span class="pun">};</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">Offset</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> T</span><span class="pun">...</span><span class="pln">I </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> print_offset_sequence</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">integer_sequence </span><span class="pun">&lt;</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> I</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        print_sequence</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">integer_sequence </span><span class="pun">&lt;</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> T</span><span class="pun">(</span><span class="pln">I </span><span class="pun">+</span><span class="pln"> </span><span class="typ">Offset</span><span class="pun">)...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">());</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// تحديد التسلسلات بشكل صريح</span><span class="pln">
    print_sequence</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">integer_sequence </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">());</span><span class="pln">
    print_sequence</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">integer_sequence </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">,</span><span class="pln"> </span><span class="str">'f'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'o'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'o'</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">());</span><span class="pln">
    </span><span class="com">// توليد التسلسلات</span><span class="pln">
    print_sequence</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">make_index_sequence </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">());</span><span class="pln">
    print_sequence</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">make_integer_sequence </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">short</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">());</span><span class="pln">
    print_offset_sequence </span><span class="pun">&lt;</span><span class="pln"> </span><span class="str">'A'</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">make_integer_sequence </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">,</span><span class="pln"> </span><span class="lit">26</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">());</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يَستخدم قالب الدّالة <code>‎print_sequence()‎</code> قائمة التهيئة <code>‎std::initializer_list&lt;bool&gt;‎</code> عند توسيع تسلسل الأعداد الصحيحة لضمان ترتيب التقييم، وتجنّب إنشاء متغيّر [مصفوفة] غير مستخدم.
</p>

<h3>
	تحويل سلسلة من الفهارس إلى نُسخ من عنصر ما
</h3>

<p>
	يؤدي توسيع حزمة معاملات من الفهارس في تعبير فاصلة (comma expression) يحمل قيمةً ما، إلى إنشاء نسخة من القيمة المقابلة لكل فهرس. ويرى المُصرِّفان <code>‎gcc‎</code> و <code>‎clang‎</code> أنّ الفهرس ليس له أيّ تأثير، لذا يطلقان تحذيرًا بشأنه (يمكن إسكات <code>‎gcc‎</code> عبر تحويل الفهرس إلى قيمة فارغة <code>‎void‎</code>):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3142_104" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;algorithm&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;array&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iterator&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;string&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;utility&gt;</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pun">...</span><span class="pln">I </span><span class="pun">&gt;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">array </span><span class="pun">&lt;</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">...(</span><span class="pln">I</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> make_array</span><span class="pun">(</span><span class="pln">T
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> value</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">index_sequence </span><span class="pun">&lt;</span><span class="pln"> I</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">array </span><span class="pun">&lt;</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">...(</span><span class="pln">I</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="pun">(</span><span class="pln">I</span><span class="pun">,</span><span class="pln"> value</span><span class="pun">)...</span><span class="pln">
        </span><span class="pun">};</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> N</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">array </span><span class="pun">&lt;</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> N </span><span class="pun">&gt;</span><span class="pln"> make_array</span><span class="pun">(</span><span class="pln">T
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> value</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> make_array</span><span class="pun">(</span><span class="pln">value</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_index_sequence </span><span class="pun">&lt;</span><span class="pln"> N </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">());</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> array </span><span class="pun">=</span><span class="pln"> make_array </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">20</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">(</span><span class="str">"value"</span><span class="pun">));</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">copy</span><span class="pun">(</span><span class="pln">array</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> array</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">ostream_iterator </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">,</span><span class="pln"> </span><span class="str">" "</span><span class="pun">));</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617022533="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة مقالات عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصول 51 وحتى 60 من كتاب <a data-ss1617022533="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">952</guid><pubDate>Sat, 08 Aug 2020 18:00:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x646;&#x648;&#x639; std::map: &#x627;&#x644;&#x642;&#x648;&#x627;&#x645;&#x64A;&#x633; &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D9%86%D9%88%D8%B9-stdmap-%D8%A7%D9%84%D9%82%D9%88%D8%A7%D9%85%D9%8A%D8%B3-%D9%81%D9%8A-cpp-r942/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/30.jpg.b83c95ba66b2073af53833acfc85d791.jpg" /></p>

<p>
	نبدأ بدايةً بسرد بعض الأمور المتعلقة بالقاموس أو النوع std::map:
</p>

<ul>
<li>
		لاستخدام أحد الصنفين <code>‎std::map‎</code> (القواميس) أو <code>‎std::multimap‎</code> (القواميس المتعدّدة)، يجب تضمين الترويسة<map>.</map>
</li>
	<li>
		تُبقي القواميس والقواميس المتعدّدة عناصرها مرتّبة تصاعديًا وفقًا للمفاتيح، وفي حالة القواميس المتعدّدة (<code>‎std::multimap‎</code>) فإن القيم التي لها نفس المفتاح لا تُرتّب.
	</li>
	<li>
		الاختلاف الأساسي بين القواميس والقواميس المتعدّدة هو أنّ القواميس لا تسمح بأن تكون هناك أكثر من قيمة واحدة مرتبطة بالمفتاح نفسه، وذلك على خلاف القواميس المتعدّدة.
	</li>
	<li>
		تُقدَّم القواميس كأشجار بحث ثنائية (binary search trees). لذا تستغرق دوالّّ <code>‎search()‎</code> و <code>‎insert()‎</code> و <code>‎erase()‎</code> وقتًا لوغاريتميًا يساوي Θ(log n)‎ في المتوسط. إن أردت عمليات تأخذ وقتًا ثابتًا، فاستخدم <code>‎std::unordered_map‎</code>.
	</li>
	<li>
		تعقيد الدالّتين <code>‎size()‎</code> و <code>‎empty()‎</code> يساوي (Θ(1، إذ يُخزّن عدد العُقَد مؤقتًا لتجنّب المرور عبر الشجرة في كل مرّة تُستدعى فيه هاتان الدالتان.
	</li>
</ul>
<h2>
	الوصول إلى العناصر
</h2>

<p>
	تأخذ القواميس أزواجًا قيمة-مفتاح <code>‎(key, value)‎</code> كمُدخلات. يوضح المثال التالي كيفية تهيئة <code>std::map</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_7" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">map</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> ranking </span><span class="pun">{</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="str">"stackoverflow"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">),</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="str">"docs-beta"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">};</span></pre>

<p>
	يمكن إدراج العناصر في القواميس على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_9" style="">
<span class="pln">ranking</span><span class="pun">[</span><span class="str">"stackoverflow"</span><span class="pun">]=</span><span class="lit">2</span><span class="pun">;</span><span class="pln">
ranking</span><span class="pun">[</span><span class="str">"docs-beta"</span><span class="pun">]=</span><span class="lit">1</span><span class="pun">;</span></pre>

<p>
	في المثال أعلاه، إذا كان المفتاح <code>‎stackoverflow‎</code> موجودًا من قبل، فستُحدّث قيمته إلى 2. وإن لم يكن موجودًا، فسيُنشأ مدخل جديد.
</p>

<p>
	يمكن الوصول إلى عناصر القاموس <code>std::map</code> مباشرةً عن طريق تمرير المفتاح كفهرس:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_11" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> ranking</span><span class="pun">[</span><span class="pln"> </span><span class="str">"stackoverflow"</span><span class="pln"> </span><span class="pun">]</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></pre>

<p>
	لاحظ أنّ استخدام عامل الفهرسة <code>‎operator[]‎</code> على القاموس سيؤدّي إلى إدراج قيمة جديدة باستخدام المفتاح الذي تمّ الاستعلام عنه في القاموس. هذا يعني أنّه لا يمكنك استخدامه على القواميس الثابتة <code>‎const std::map‎</code>، حتى لو كان المفتاح مخزّنًا سلفًا في القاموس. ولمنع هذا الإدراج، تحقق من وجود العنصر (مثلًا باستخدام <code>‎find()‎</code>) أو استخدم <code>‎at()‎</code> كما هو موضّح أدناه.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	يمكن الوصول إلى عناصر القواميس باستخدام التابع <code>‎at()‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_13" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> ranking</span><span class="pun">.</span><span class="pln">at</span><span class="pun">(</span><span class="str">"stackoverflow"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></pre>

<p>
	لاحظ أنّ التابع <code>‎at()‎</code> سيرفع اعتراض <code>‎std::out_of_range‎</code> إن لم تحتوي الحاوية على العنصر المطلوب. يمكن الوصول في القواميس والقواميس المتعدّدة إلى العناصر باستخدام <a data-ss1617022530="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-8-%D8%A7%D9%84%D9%85%D9%83%D8%B1%D8%A7%D8%B1%D8%A7%D8%AA-iterators-%D9%81%D9%8A-cpp-r892/" rel="">المُكرّرات</a>:
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_15" style="">
<span class="com">// begin() مثال على استخدام</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">multimap</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&gt;</span><span class="pln"> mmp </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="str">"stackoverflow"</span><span class="pun">),</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="str">"docs-beta"</span><span class="pun">),</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="str">"stackexchange"</span><span class="pun">)</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> mmp</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">();</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> it </span><span class="pun">-&gt;</span><span class="pln"> first </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" : "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> it </span><span class="pun">-&gt;</span><span class="pln"> second </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// "1 : docs-beta"</span><span class="pln">
it</span><span class="pun">++;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> it </span><span class="pun">-&gt;</span><span class="pln"> first </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" : "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> it </span><span class="pun">-&gt;</span><span class="pln"> second </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// "2 : stackoverflow"</span><span class="pln">
it</span><span class="pun">++;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> it </span><span class="pun">-&gt;</span><span class="pln"> first </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" : "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> it </span><span class="pun">-&gt;</span><span class="pln"> second </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// "2 : stackexchange"</span><span class="pln">

</span><span class="com">// rbegin() مثال على استخدام</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">map</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&gt;</span><span class="pln"> mp </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="str">"stackoverflow"</span><span class="pun">),</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="str">"docs-beta"</span><span class="pun">),</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="str">"stackexchange"</span><span class="pun">)</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">auto</span><span class="pln"> it2 </span><span class="pun">=</span><span class="pln"> mp</span><span class="pun">.</span><span class="pln">rbegin</span><span class="pun">();</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> it2 </span><span class="pun">-&gt;</span><span class="pln"> first </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" : "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> it2 </span><span class="pun">-&gt;</span><span class="pln"> second </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">//  "2 : stackoverflow"</span><span class="pln">
it2</span><span class="pun">++;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> it2 </span><span class="pun">-&gt;</span><span class="pln"> first </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" : "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> it2 </span><span class="pun">-&gt;</span><span class="pln"> second </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// "1 : docs-beta"</span></pre>

<h2>
	إدراج عناصر في القواميس
</h2>

<p>
	لا يمكن إدراج عنصر في قاموس إلّا إن كان مفتاحه غير موجود من قبل في القاموس. على سبيل المثال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_17" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">map</span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> </span><span class="typ">size_t</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> fruits_count</span><span class="pun">;</span></pre>

<ul>
<li>
		يمكن إدراج زوج قيمة-مفتاح (key-value) في قاموس عبر التابع <code>‎insert()‎</code>، والذي يتطلب زوجًا (<code>‎pair‎</code>) كوسيط:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_20" style="">
<span class="pln">fruits_count</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">({</span><span class="str">"grapes"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">20</span><span class="pun">});</span><span class="pln">
fruits_count</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">make_pair</span><span class="pun">(</span><span class="str">"orange"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">30</span><span class="pun">));</span><span class="pln">
fruits_count</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">pair</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> </span><span class="typ">size_t</span><span class="pun">&gt;(</span><span class="str">"banana"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">40</span><span class="pun">));</span><span class="pln">
fruits_count</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="typ">map</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> </span><span class="typ">size_t</span><span class="pun">&gt;::</span><span class="pln">value_type</span><span class="pun">(</span><span class="str">"cherry"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">50</span><span class="pun">));</span></pre>

<p>
	تعيد الدالّة <code>‎insert()‎</code> زوجًا مؤلّفًا من <a data-ss1617022530="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-8-%D8%A7%D9%84%D9%85%D9%83%D8%B1%D8%A7%D8%B1%D8%A7%D8%AA-iterators-%D9%81%D9%8A-cpp-r892/" rel="">مُكرّر</a> وقيمة بوليانية <code>‎bool‎</code>:
</p>

<ul>
<li>
		إن نجحت عملية الإدراج فإنّ المكرّر يشير إلى العنصر المُدرج حديثًا، وستكون القيمة البوليانية <code>‎bool‎</code> المعادة صحيحة (<code>‎true‎</code>).
	</li>
	<li>
		إن كان في القاموس مدخل له نفس المفتاح <code>‎key‎</code> فستفشل عملية الإدراج. وحينها سيشير المكرّر إلى العنصر الذي له ذلك المفتاح، وستسَاوي <code>‎bool‎</code> القيمة <code>‎false‎</code> يمكن استخدام الطريقة التالية لدَمج عمليتي الإدراج والبحث معًا:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_22" style="">
<span class="kwd">auto</span><span class="pln"> success </span><span class="pun">=</span><span class="pln"> fruits_count</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">({</span><span class="str">"grapes"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">20</span><span class="pun">});</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">success</span><span class="pun">.</span><span class="pln">second</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// موجود سلفا في القاموس 'grapes' </span><span class="pln">
    success</span><span class="pun">.</span><span class="pln">first </span><span class="pun">-&gt;</span><span class="pln"> second </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">20</span><span class="pun">;</span><span class="pln"> </span><span class="com">// الدخول إلى المكرر لتحديث القيمة</span><span class="pln">
</span><span class="pun">}</span></pre>

<ul>
<li>
		يُستخدم عامل الفهرسة للوصول إلى العناصر الموجودة في القاموس، أو إدراج عناصر جديدة في حال لم تكن موجودة:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_24" style="">
<span class="pln">fruits_count</span><span class="pun">[</span><span class="str">"apple"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span></pre>

<p>
	المشكلة في هذا العامل أنه يمنع المستخدم من التحقّق مما إذا كان العنصر موجودًا بالفعل. وفي حال لم يكن العنصر موجودًا، فسيُنشئه العامل <code>std::map::operator[]‎</code> ضمنيًا، إذ سيهيِّئه باستخدام المُنشئ الافتراضي قبل إعادة كتابته بالقيمة المعطاة..
</p>

<ul>
<li>
		يمكن استخدام التابع <code>‎insert()‎</code> لإضافة عدّة عناصر دفعة واحدة عبر تمرير قائمة من الأزواج، يعيد هذا الإصدار من <code>‎insert()‎</code> القيمة الفارغة void:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_26" style="">
<span class="pln">fruits_count</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">({{</span><span class="str">"apricot"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="str">"jackfruit"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="str">"lime"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="str">"mango"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pun">}});</span></pre>

<p>
	يمكن أيضًا استخدام <code>‎insert()‎</code> لإضافة عدّة عناصر باستخدام مُكرّرات تشير إلى بداية ونهاية <code>‎value_type‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_28" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">map</span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> </span><span class="typ">size_t</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> fruit_list</span><span class="pun">{</span><span class="pln"> </span><span class="pun">{</span><span class="str">"lemon"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="str">"olive"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="str">"plum"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">}};</span><span class="pln">
fruits_count</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">fruit_list</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> fruit_list</span><span class="pun">.</span><span class="pln">end</span><span class="pun">());</span></pre>

<p>
	مثال: سنضيف عنصرًا يساوي مفتاحه <code>fruit</code> وقيمته 1، وإن المفتاح موجودًا فلن تفعل <code>fruit_count</code> أي شيء.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_30" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">map</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> </span><span class="typ">size_t</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> fruits_count</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string fruit</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">cin </span><span class="pun">&gt;&gt;</span><span class="pln"> fruit</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      </span><span class="kwd">auto</span><span class="pln"> ret </span><span class="pun">=</span><span class="pln"> fruits_count</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">({</span><span class="pln">
        fruit</span><span class="pun">,</span><span class="pln">
        </span><span class="lit">1</span><span class="pln">
    </span><span class="pun">});</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">ret</span><span class="pun">.</span><span class="pln">second</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// موجود سلفا 'fruit' </span><span class="pln">
        </span><span class="pun">++</span><span class="pln">ret</span><span class="pun">.</span><span class="pln">first </span><span class="pun">-&gt;</span><span class="pln"> second</span><span class="pun">;</span><span class="pln"> </span><span class="com">// زيادة العداد</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	التعقيد الزمني لعملية الإدراج هو O(log n)‎، ذلك أنّ القواميس تُنفَّذ على هيئة أشجار.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	يمكن إنشاء زوج (<code>‎pair‎</code>) بشكل صريح باستخدام <code>‎make_pair()‎</code> و <code>‎emplace()‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_32" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">map</span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> runs</span><span class="pun">;</span><span class="pln">
runs</span><span class="pun">.</span><span class="pln">emplace</span><span class="pun">(</span><span class="str">"Babe Ruth"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">714</span><span class="pun">);</span><span class="pln">
runs</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">make_pair</span><span class="pun">(</span><span class="str">"Barry Bonds"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">762</span><span class="pun">));</span></pre>

<p>
	يمكننا استخدام <code>‎emplace_hint()‎</code> إذا علمنا أين سيُدرج العنصر الجديد من أجل تحديد مكرّر <code>‎hint‎</code>. إذا استطعنا إدراج العنصر الجديد قبل <code>‎hint‎</code> مباشرة فيمكن إجراء الإدراج في وقت ثابت، وإلا فإنّه سيتصرف مثل التابع <code>‎emplace()‎</code>. انظر المثال التالي حيث نطلب الحصول على مكرر يشير إلى العنصر المُدرَج، ويكون العنصر التالي قبل <code>Barry Bonds</code> لذا سيُدرَج قبل <code>it</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_34" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">map</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> runs</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> runs</span><span class="pun">.</span><span class="pln">emplace</span><span class="pun">(</span><span class="str">"Barry Bonds"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">762</span><span class="pun">);</span><span class="pln">
runs</span><span class="pun">.</span><span class="pln">emplace_hint</span><span class="pun">(</span><span class="pln">it</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Babe Ruth"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">714</span><span class="pun">);</span></pre>

<h2>
	البحث في القواميس والقواميس المتعدّدة
</h2>

<p>
	هناك عدّة طرق للبحث عن مفتاح في قاموس أو قاموس متعدّد .
</p>

<ul>
<li>
		للحصول على مُكرّر يشير إلى أوّل ظهور لمفتاح معيّن، استخدم الدالّة <code>‎find()‎</code> التي تعيد <code>‎end()‎</code> إن لم يكن المفتاح موجودًا.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_36" style="">
<span class="pln"> std</span><span class="pun">::</span><span class="typ">multimap</span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> mmp</span><span class="pun">{</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pun">}</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> mmp</span><span class="pun">.</span><span class="pln">find</span><span class="pun">(</span><span class="lit">6</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">it </span><span class="pun">!=</span><span class="pln"> mmp</span><span class="pun">.</span><span class="pln">end</span><span class="pun">())</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> it </span><span class="pun">-&gt;</span><span class="pln"> first </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> it </span><span class="pun">-&gt;</span><span class="pln"> second </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 6, 5</span><span class="pln">
</span><span class="kwd">else</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Value does not exist!"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">

it </span><span class="pun">=</span><span class="pln"> mmp</span><span class="pun">.</span><span class="pln">find</span><span class="pun">(</span><span class="lit">66</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">it </span><span class="pun">!=</span><span class="pln"> mmp</span><span class="pun">.</span><span class="pln">end</span><span class="pun">())</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> it </span><span class="pun">-&gt;</span><span class="pln"> first </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> it </span><span class="pun">-&gt;</span><span class="pln"> second </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">else</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Value does not exist!"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// سيتم تنفيذ هذا السطر</span></pre>

<ul>
<li>
		هناك طريقة أخرى لمعرفة ما إذا كان قاموس أو قاموس متعدّد يحتوي على مدخَل معيّن، وهي استخدام الدالّة <code>‎count()‎</code>، والتي تحسب عدد القيم المرتبطة بمفتاح معين، وبما أن القواميس لا تربط إلا قيمة واحدة فقط بكلّ مفتاح، فإنّ الدالّة <code>‎count()‎</code> ستُعيد إمّا 0 -إن كان المفتاح غير موجود-، أو 1 -إن كان موجودًا-، أما بالنسبة إلى القواميس المتعدّدة فيمكن أن تعيد الدالّةُ <code>‎count()‎</code> قيمًا أكبر من 1 لأنّها تُجيز ربط عدّة قيم بنفس المفتاح.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_38" style="">
<span class="pln"> std</span><span class="pun">::</span><span class="typ">map</span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> mp</span><span class="pun">{</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pun">}</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">mp</span><span class="pun">.</span><span class="pln">count</span><span class="pun">(</span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="com">// المفتاح 3 موجود في القاموس</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"The key exists!"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// سيتم تنفيذ هذا السطر</span><span class="pln">
</span><span class="kwd">else</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"The key does not exist!"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></pre>

<p>
	إن كان كل ما تريده هو التحقق من وجود عنصر ما، فإنّ <code>‎find‎</code> أفضل بلا شكّ: فعملُها واضح من اسمها، وبالنسبة للقواميس المتعدّدة <code>‎multimaps‎</code>، فإنّها تتوقف بمجرّد العثور على أول عنصر مطابِق.
</p>

<ul>
<li>
		يمكن أن ترتبط عدّة عناصر بنفس المفتاح في حالة القواميس المتعدّدة، وللحصول على تلك العناصر، يمكن استخدام الدالّة <code>‎equal_range()‎</code> التي تُعيد زوجًا يحتوي مُكرّر الحدّ الأدنى - iterator lower bound - (مُضمّن) ومُكرّر الحدّ الأعلى - iterator upper bound - (غير مُضمّن) على التوالي. إذا لم يكن المفتاح موجودًا، فسيُشير كلا المُكرّرين إلى <code>‎end()‎</code>.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_40" style="">
<span class="kwd">auto</span><span class="pln"> eqr </span><span class="pun">=</span><span class="pln"> mmp</span><span class="pun">.</span><span class="pln">equal_range</span><span class="pun">(</span><span class="lit">6</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> st </span><span class="pun">=</span><span class="pln"> eqr</span><span class="pun">.</span><span class="pln">first</span><span class="pun">,</span><span class="pln"> en </span><span class="pun">=</span><span class="pln"> eqr</span><span class="pun">.</span><span class="pln">second</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> st</span><span class="pun">;</span><span class="pln"> it </span><span class="pun">!=</span><span class="pln"> en</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">it</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> it </span><span class="pun">-&gt;</span><span class="pln"> first </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> it </span><span class="pun">-&gt;</span><span class="pln"> second </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// 6, 7</span></pre>

<h2>
	تهيئة القواميس والقواميس المتعددة
</h2>

<p>
	يمكن تهيئة قاموس أو قاموس متعدّد عبر توفير أزواج قيمة-مفتاح مفصولة بفاصلة <code>,</code>، ويمكن توفير أزواج قيمة-مفتاح وفق الصيغة <code>‎{key, value}‎</code> أو إنشاؤها بشكل صريح بواسطة الدالّة <code>‎std::make_pair(key, value)‎</code>. ولأنّ القواميس لا تسمح بالمفاتيح المكرّرة ولأن عامل الفاصلة (comma operator) يعمل من اليمين إلى اليسار، فسَتتم الكتابة على الزوج الموجود على اليمين باستخدام الزوج ذي المفتاح نفسه والمَوجود على اليسار.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_42" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">multimap</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&gt;</span><span class="pln"> mmp </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="str">"stackoverflow"</span><span class="pun">),</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="str">"docs-beta"</span><span class="pun">),</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="str">"stackexchange"</span><span class="pun">)</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// 1 docs-beta</span><span class="pln">
</span><span class="com">// 2 stackoverflow</span><span class="pln">
</span><span class="com">// 2 stackexchange</span><span class="pln">

std</span><span class="pun">::</span><span class="typ">map</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&gt;</span><span class="pln"> mp </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="str">"stackoverflow"</span><span class="pun">),</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="str">"docs-beta"</span><span class="pun">),</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="str">"stackexchange"</span><span class="pun">)</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// 1 docs-beta</span><span class="pln">
</span><span class="com">// 2 stackoverflow</span></pre>

<p>
	كلاهما يمكن تهِيئتهما عبر المكرّرات. انظر:
</p>

<ul>
<li>
		من مكرر <code>std::map</code> أو <code>std::multimap</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_44" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">multimap</span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> mmp</span><span class="pun">{</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">},</span><span class="pln">
</span><span class="pun">{</span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pun">}</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="com">// {1, 2}, {3, 4}, {3, 4}, {6, 5}, {6, 8}, {6, 7}, {8, 9}</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> mmp</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">();</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">advance</span><span class="pun">(</span><span class="pln">it</span><span class="pun">,</span><span class="lit">3</span><span class="pun">);</span><span class="pln">                </span><span class="com">// {6, 5} حرك المؤشر على أول </span><span class="pln">
std</span><span class="pun">::</span><span class="typ">map</span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> mp</span><span class="pun">(</span><span class="pln">it</span><span class="pun">,</span><span class="pln"> mmp</span><span class="pun">.</span><span class="pln">end</span><span class="pun">());</span><span class="pln">    </span><span class="com">// {6, 5}, {8, 9}</span></pre>

<ul>
<li>
		من مصفوفة الأزواج:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_46" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">pair</span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> arr</span><span class="pun">[</span><span class="lit">10</span><span class="pun">];</span><span class="pln">
arr</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">};</span><span class="pln">
arr</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">};</span><span class="pln">
arr</span><span class="pun">[</span><span class="lit">2</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">};</span><span class="pln">
arr</span><span class="pun">[</span><span class="lit">3</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">};</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">map</span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> mp</span><span class="pun">(</span><span class="pln">arr</span><span class="pun">,</span><span class="pln">arr</span><span class="pun">+</span><span class="lit">4</span><span class="pun">);</span><span class="pln"> </span><span class="com">//{0 , 1}, {1, 3}, {2, 5}</span></pre>

<ul>
<li>
		من متجه <code>std::vector</code> من الأزواج <code>std::pair</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_48" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">pair</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v</span><span class="pun">{</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">}</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">multimap</span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> mp</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">());</span><span class="pln">
</span><span class="com">// {1, 5}, {3, 6}, {3, 2}, {5, 1}</span></pre>

<h2>
	التحقق من عدد العناصر
</h2>

<p>
	حاوية <code>std::map</code> بها الدالة التابعة <code>‎empty()‎</code>، التي تعيد إحدى القيمتين <code>‎true‎</code> أو <code>‎false‎</code> حسب حالة القاموس هل فارغ أم لا، بينما تعيد <code>‎size()‎</code> عدد العناصر المخزّنة في القاموس:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_50" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">map</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&gt;</span><span class="pln"> rank </span><span class="pun">{{</span><span class="str">"facebook.com"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">}</span><span class="pln"> </span><span class="pun">,{</span><span class="str">"google.com"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="str">"youtube.com"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">}};</span><span class="pln">
</span><span class="kwd">if</span><span class="pun">(!</span><span class="pln">rank</span><span class="pun">.</span><span class="pln">empty</span><span class="pun">()){</span><span class="pln">
 std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Number of elements in the rank map: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> rank</span><span class="pun">.</span><span class="pln">size</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">else</span><span class="pun">{</span><span class="pln">
 std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"The rank map is empty"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	أنواع القواميس
</h2>

<h3>
	القواميس العادية
</h3>

<p>
	القاموس عبارة عن حاوية ترابطية (associative container) تحتوي على أزواج "قيمة-مفتاح".
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_52" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;string&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;map&gt;</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">map</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> </span><span class="typ">size_t</span><span class="pun">&gt;</span><span class="pln"> fruits_count</span><span class="pun">;</span></pre>

<p>
	في المثال أعلاه، تمثّل <code>‎std::string‎</code> نوع المفتاح، وتمثل <code>‎size_t‎</code> القيمة.
</p>

<p>
	يتصرّف المفتاح كفهرس في القاموس، ويجب أن يكون كل مفتاح فريدًا، ومُرتّبًا.
</p>

<ul>
<li>
		إذا كنت بحاجة إلى قاموس يسمح بأن ترتبط عدّة قيم بنفس المفتاح، فعليك استخدام قاموس متعدّد <code>‎multimap‎</code> كما هو موضّح أدناه.
	</li>
	<li>
		إذا لم يكن هناك أيّ ترتيب مرتبط بنوع القيمة، أو إذا كنت تريد تجاوز الترتيب الافتراضي، فيمكنك إنشاء ترتيب خاصّ بك عبر:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_54" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;string&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;map&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;cstring&gt;</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">StrLess</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">bool</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">()(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&amp;</span><span class="pln"> a</span><span class="pun">,</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&amp;</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> strncmp</span><span class="pun">(</span><span class="pln">a</span><span class="pun">.</span><span class="pln">c_str</span><span class="pun">(),</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">c_str</span><span class="pun">(),</span><span class="pln"> </span><span class="lit">8</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
        </span><span class="com">// قارن الأحرف الثمانية الأولى فقط</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">map</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> </span><span class="typ">size_t</span><span class="pun">,</span><span class="pln"> </span><span class="typ">StrLess</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> fruits_count2</span><span class="pun">;</span></pre>

<p>
	إن أعادت دالّة الموازنة <code>‎StrLess‎</code> القيمة <code>‎false‎</code>، فيكون المفتَاحان متساويَين، حتى لو كانت محتوياتهما مختلفة.
</p>

<h3>
	القواميس المتعددة
</h3>

<p>
	تسمح القواميس المتعدّدة بتخزين عدّة أزواج لها نفس المفتاح في القاموس، وإلا فإنّ واجهتها وطريقة إنشائها ستشبه القواميس العادية.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_56" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;string&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;map&gt;</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">multimap</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> </span><span class="typ">size_t</span><span class="pun">&gt;</span><span class="pln"> fruits_count</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">multimap</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> </span><span class="typ">size_t</span><span class="pun">,</span><span class="pln"> </span><span class="typ">StrLess</span><span class="pun">&gt;</span><span class="pln"> fruits_count2</span><span class="pun">;</span></pre>

<h3>
	قواميس التجزئة (القواميس غير المرتبة)
</h3>

<p>
	تُخزِّن قواميس التجزئة (hash maps) أزواج "المفتاح-القيمة" بطريقة مشابهة للقواميس العادية، إلا أنها لا ترتّب العناصر وفقًا للمفاتيح، وإنما تُستخدم قيمة التجزئة (hash value) الخاصة بالمفتاح للوصول بسرعة إلى الأزواج قيمة-مفتاح المطلوبة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_58" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;string&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;unordered_map&gt;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">unordered_map</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> </span><span class="typ">size_t</span><span class="pun">&gt;</span><span class="pln"> fruits_count</span><span class="pun">;</span></pre>

<p>
	القواميس غير المرتّبة أسرع عادةً، بيْد أنه لا يمكن توقّع ترتيب عناصرها. على سبيل المثال، يكون التكرار على عناصر قاموس غير مرتب <code>‎unordered_map‎</code> بترتيب عشوائي.
</p>

<h2>
	حذف العناصر
</h2>

<p>
	إزالة جميع العناصر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_60" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">multimap</span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> mmp</span><span class="pun">{</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pun">}</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
mmp</span><span class="pun">.</span><span class="pln">clear</span><span class="pun">();</span><span class="pln"> </span><span class="com">// أصبح القاموس المتعدّد فارغا</span></pre>

<p>
	إزالة عنصر ما باستخدام مكرّر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_62" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">multimap</span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> mmp</span><span class="pun">{</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pun">}</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="com">// {1, 2}, {3, 4}, {3, 4}, {6, 5}, {6, 7}, {8, 9}</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> mmp</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">();</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">advance</span><span class="pun">(</span><span class="pln">it</span><span class="pun">,</span><span class="lit">3</span><span class="pun">);</span><span class="pln"> </span><span class="com">// {6, 5} إزاحة المؤشّر إلى أول</span><span class="pln">
mmp</span><span class="pun">.</span><span class="pln">erase</span><span class="pun">(</span><span class="pln">it</span><span class="pun">);</span><span class="pln"> </span><span class="com">// {1, 2}, {3, 4}, {3, 4}, {6, 7}, {8, 9}</span></pre>

<p>
	إزالة جميع العناصر في نطاق معيّن:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_64" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">multimap</span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> mmp</span><span class="pun">{</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pun">}</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="com">// {1, 2}, {3, 4}, {3, 4}, {6, 5}, {6, 7}, {8, 9}</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> mmp</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> it2 </span><span class="pun">=</span><span class="pln"> it</span><span class="pun">;</span><span class="pln">
it</span><span class="pun">++;</span><span class="pln">                </span><span class="com">// {3, 4} إزاحة المؤشّر إلى أول</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">advance</span><span class="pun">(</span><span class="pln">it2</span><span class="pun">,</span><span class="lit">3</span><span class="pun">);</span><span class="pln">        </span><span class="com">// {6, 5} إزاحة المؤشّر الثاني إلى أول</span><span class="pln">
mmp</span><span class="pun">.</span><span class="pln">erase</span><span class="pun">(</span><span class="pln">it</span><span class="pun">,</span><span class="pln">it2</span><span class="pun">);</span><span class="pln"> </span><span class="com">// {1, 2}, {6, 5}, {6, 7}, {8, 9}</span></pre>

<p>
	إزالة جميع العناصر التي لها مفتاح معيّن:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_66" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">multimap</span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> mmp</span><span class="pun">{</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pun">}</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="com">// {1, 2}, {3, 4}, {3, 4}, {6, 5}, {6, 7}, {8, 9}</span><span class="pln">
mmp</span><span class="pun">.</span><span class="pln">erase</span><span class="pun">(</span><span class="lit">6</span><span class="pun">);</span><span class="pln"> </span><span class="com">// {1, 2}, {3, 4}, {3, 4}, {8, 9}</span></pre>

<p>
	إزالة العناصر التي تحقق شرطًا <code>‎pred‎</code> معيّنا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_68" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">map</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> m</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> m</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">it </span><span class="pun">!=</span><span class="pln"> m</span><span class="pun">.</span><span class="pln">end</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">pred</span><span class="pun">(</span><span class="pln"> </span><span class="pun">*</span><span class="pln">it</span><span class="pun">))</span><span class="pln">
        it </span><span class="pun">=</span><span class="pln"> m</span><span class="pun">.</span><span class="pln">erase</span><span class="pun">(</span><span class="pln">it</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">else</span><span class="pln">
        </span><span class="pun">++</span><span class="pln">it</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	التكرار على القواميس والقواميس المتعددة
</h2>

<p>
	يمكن التكرار على القواميس والقواميس المتعدّدة بالطرق التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_70" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">multimap</span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> mmp</span><span class="pun">{</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pun">}</span><span class="pln"> </span><span class="pun">};</span><span class="pln">

</span><span class="com">// C++11 حلقة نطاقية - منذ</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> x</span><span class="pun">:</span><span class="pln"> mmp</span><span class="pun">)</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> x</span><span class="pun">.</span><span class="pln">first </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">":"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> x</span><span class="pun">.</span><span class="pln">second </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">

</span><span class="com">//أمامي، سيمرُّ على العناصر من الأول حتى الأخير for مكرّر</span><span class="pln">
</span><span class="com">// std::map&lt; int, int &gt;::iterator سيكون من النوع</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> mmp</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">();</span><span class="pln"> it </span><span class="pun">!=</span><span class="pln"> mmp</span><span class="pun">.</span><span class="pln">end</span><span class="pun">();</span><span class="pln"> </span><span class="pun">++</span><span class="pln">it</span><span class="pun">)</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> it </span><span class="pun">-&gt;</span><span class="pln"> first </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">":"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> it </span><span class="pun">-&gt;</span><span class="pln"> second </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">//افعل شيئا ما بالمكرر</span><span class="pln">

</span><span class="com">// عكسي، سيمُرّ على العناصر من الأخير إلى الأول for مكرر</span><span class="pln">
</span><span class="com">// std::map&lt; int, int &gt;::reverse_iterator سيكون من النوع</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> mmp</span><span class="pun">.</span><span class="pln">rbegin</span><span class="pun">();</span><span class="pln"> it </span><span class="pun">!=</span><span class="pln"> mmp</span><span class="pun">.</span><span class="pln">rend</span><span class="pun">();</span><span class="pln"> </span><span class="pun">++</span><span class="pln">it</span><span class="pun">)</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> it </span><span class="pun">-&gt;</span><span class="pln"> first </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> it </span><span class="pun">-&gt;</span><span class="pln"> second </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// افعل شيئا ما بالمكرّر </span></pre>

<p>
	يُفضّل أثناء التكرار على قاموس أو قاموس متعدّد استخدام <code>‎auto‎</code> لتجنّب التحويلات الضمنية غير المفيدة (راجع <a data-ss1617022530="1" href="https://stackoverflow.com/questions/32510183/can-the-use-of-c11s-auto-improve-performance" rel="external nofollow">هذه الإجابة في موقع StackOverFlow</a> لمزيد من التفاصيل).
</p>

<h2>
	إنشاء قاموس باستخدام الأنواع المُعرَّفة من المستخدم كمفتاح
</h2>

<p>
	لكي تكون قادرًا على استخدام صنف كمفتاح في القاموس، ينبغي أن يكون المفتاح قابلًا للنسخ <code>‎copiable‎</code> والإسناد <code>‎assignable‎</code>. يُحدَّد الترتيب داخل القاموس من قِبل الوسيط الثالث المُمرّر إلى القالب (والوسيط الممرّر إلى المُنشئ، في حال استخدامه) ويساوي افتراضيًا <code>‎std::less&lt;KeyType&gt;‎</code>، والذي يساوي (افتراضيًا) عامل المقارنة <code>‎&lt;‎</code>. لكن لا يلزم استخدام عامل المقارنة الافتراضي إذ يمكنك كتابة معامل مقارنة خاصّ بك (يفضل أن يكون كائنًا داليًا - functional object):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_72" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">CmpMyType</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">bool</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">()(</span><span class="pln"> </span><span class="typ">MyType</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> lhs</span><span class="pun">,</span><span class="pln"> </span><span class="typ">MyType</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> rhs </span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">//  ...</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	في C++‎، يجب أن يكون شرط "المقارنة" (compare predicate) ترتيبًا ضعيفًا صارمًا (strict weak ordering)، ويجب أن يعيد تعبيرُ <code>‎compare(X,X)‎</code> القيمة <code>‎false‎</code> مهما كانت قيمة <code>‎X‎</code>، فإن أعاد التعبير <code>‎CmpMyType()(a, b)‎</code> القيمة <code>true</code>، فإنّ التعبيرَ <code>‎CmpMyType()(b, a)‎</code> ينبغي أن يعيد <code>false</code>، وفي حال أعاد كلاهما القيمة <code>false</code>، فسيُعدُّ العنصران a و b متساويين.
</p>

<h3>
	الترتيب الضعيف الصارم
</h3>

<p>
	هذا مصطلح رياضيّاتي لتعريف العلاقة بين كائنين. ويعني:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		يكون الكائنان x و y متساويين إن كان كل من f(x, y)‎ وf(y, x)‎ خاطئين. لاحظ أنّ كل كائن يكون مكافئًا لنفسه.
	</p>
</blockquote>

<p>
	في C++‎، هذا يعني أنه إن كان لديك كائنان من نوع معيّن، فيجب أن يتحقّق الجدول التالي عند مقارنتهما بواسطة المُعامل <code>‎&lt;‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_74" style="">
<span class="pln">X    a</span><span class="pun">;</span><span class="pln">
X    b</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Condition</span><span class="pun">:</span><span class="pln">                      </span><span class="typ">Test</span><span class="pun">:</span><span class="pln">     </span><span class="typ">Result</span><span class="pln">
a is equivalent to b</span><span class="pun">:</span><span class="pln">       a </span><span class="pun">&lt;</span><span class="pln"> b     </span><span class="kwd">false</span><span class="pln">
a is equivalent to b        b </span><span class="pun">&lt;</span><span class="pln"> a     </span><span class="kwd">false</span><span class="pln">
a is less than b              a </span><span class="pun">&lt;</span><span class="pln"> b     </span><span class="kwd">true</span><span class="pln">
a is less than b              b </span><span class="pun">&lt;</span><span class="pln"> a     </span><span class="kwd">false</span><span class="pln">
b is less than a              a </span><span class="pun">&lt;</span><span class="pln"> b     </span><span class="kwd">false</span><span class="pln">
b is less than a              b </span><span class="pun">&lt;</span><span class="pln"> a     </span><span class="kwd">true</span></pre>

<p>
	تعتمد الطريقة التي تعرِّف بها مفهوم التكافؤ كليًا على نوع الكائن.
</p>

<h2>
	القواميس غير المرتبة
</h2>

<p>
	القواميس غير المُرتّبة <code>std::unordered_map</code> تشبه القواميس العادية، فهي حاوية ترابطية (Associative Container) تعمل على المفاتيح وقواميسها، فالمفاتيح تحقق التفرد في القاموس لعناصره، بينما تكون قيمة القاموس "map" مجرد محتوى مرتبط بالمفتاح، وأنواع البيانات الخاصة بهذا المفتاح والقاموس يمكن أن تكون أي نوع بيانات معرَّف مسبقًا أو عرَّفه المستخدم.
</p>

<h3>
	كيفية التصريح والاستخدام
</h3>

<p>
	يمكن التصريح عن قاموس غير مرتّب من أيّ نوع كما أوضحنا، وسنعرّف قاموسًا غير مرتّب في المثال التالي، يحمل الاسم <code>ﬁrst</code> باستخدام النوعين string و integer.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_76" style="">
<span class="pln">unordered_map </span><span class="pun">&lt;</span><span class="pln"> string</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> first</span><span class="pun">;</span><span class="pln"> </span><span class="com">// إعلان القاموس</span><span class="pln">
first</span><span class="pun">[</span><span class="str">"One"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> </span><span class="com">//  [] استخدام العامل</span><span class="pln">
first</span><span class="pun">[</span><span class="str">"Two"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
first</span><span class="pun">[</span><span class="str">"Three"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln">
first</span><span class="pun">[</span><span class="str">"Four"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4</span><span class="pun">;</span><span class="pln">
first</span><span class="pun">[</span><span class="str">"Five"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">

pair </span><span class="pun">&lt;</span><span class="pln"> string</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> bar </span><span class="pun">=</span><span class="pln"> make_pair</span><span class="pun">(</span><span class="str">"Nine"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pun">);</span><span class="pln"> </span><span class="com">// إنشاء زوج من نفس النوع</span><span class="pln">
first</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">bar</span><span class="pun">);</span></pre>

<h2>
	بعض الدوال الأساسية للتعامل مع القواميس
</h2>

<p>
	هذه بعض الدوال الأساسية الخاصة بالقواميس غير المرتبة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5246_78" style="">
<span class="pln">unordered_map</span><span class="pun">&lt;</span><span class="pln">data_type</span><span class="pun">,</span><span class="pln"> data_type</span><span class="pun">&gt;</span><span class="pln"> variable_name</span><span class="pun">;</span><span class="pln"> </span><span class="com">// التصريح</span><span class="pln">
variable_name</span><span class="pun">[</span><span class="pln">key_value</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> mapped_value</span><span class="pun">;</span><span class="pln"> </span><span class="com">// إدراج العناصر</span><span class="pln">
variable_name</span><span class="pun">.</span><span class="pln">find</span><span class="pun">(</span><span class="pln">key_value</span><span class="pun">);</span><span class="pln"> </span><span class="com">// إعادة مكرّر إلى قيمة المفتاح</span><span class="pln">
variable_name</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">();</span><span class="pln"> </span><span class="com">// مكرّر إلى العنصر الأول</span><span class="pln">
variable_name</span><span class="pun">.</span><span class="pln">end</span><span class="pun">();</span><span class="pln"> </span><span class="com">// مكرر إلى العنصر الأخير + 1</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617022530="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة مقالات عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصلين Chapter 50: std::map و Chapter 61: Using std::unordered_map من كتاب <a data-ss1617022530="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">942</guid><pubDate>Fri, 31 Jul 2020 13:09:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x646;&#x648;&#x639; std::vector: &#x627;&#x644;&#x645;&#x62A;&#x62C;&#x647;&#x627;&#x62A; &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D9%86%D9%88%D8%B9-stdvector-%D8%A7%D9%84%D9%85%D8%AA%D8%AC%D9%87%D8%A7%D8%AA-%D9%81%D9%8A-cpp-r941/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/29.jpg.01e75c8ccff17e99c4e1c93dce390261.jpg" /></p>

<p>
	المتّجه هو <a data-ss1617022526="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-7-%D8%A7%D9%84%D9%85%D8%B5%D9%81%D9%88%D9%81%D8%A7%D8%AA-%D9%81%D9%8A-cpp-r891/" rel="">مصفوفة</a> ديناميكية تخزّن البيانات تلقائيًّا، ويمكن الوصول إلى العناصر الموجودة في المتّجه بنفس طريقة المصفوفات، مع ميزة أنّ المتّجهات يمكن أن يتغير حجمها ديناميكيًا.
</p>

<p>
	وبشأن التخزين، تُوضع بيانات المتجه عادة في ذاكرة مُخصّصة ديناميكيًا، ومن ثم فإنها تتطلّب بعض الحمل الزائد (overhead)؛ بالمقابل تستخدم المصفوفات من نمط ‎C ومن الصنف <code>‎std::array‎</code> وحدةَ تخزين تلقائية مرتبطة بالموضع المُصرَّح عنه، وهكذا لا يكون هناك أيّ حِمل زائد.
</p>

<h2>
	الوصول إلى العناصر
</h2>

<p>
	هناك طريقتان أساسيتان للوصول إلى عناصر المتّجهات:
</p>

<ul>
<li>
		الفهارس
	</li>
	<li>
		<a data-ss1617022526="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-8-%D8%A7%D9%84%D9%85%D9%83%D8%B1%D8%A7%D8%B1%D8%A7%D8%AA-iterators-%D9%81%D9%8A-cpp-r892/" rel="">المُكرّرات</a>
	</li>
</ul>
<h3>
	الوصول عبر الفهرس
</h3>

<p>
	يمكن ذلك إما باستخدام عامل ألفهرسة <code>‎[]‎</code> أو الدالة التابعة <code>‎at()‎</code>، وكلاهما يعيد مرجعًا إلى العنصر الموجود في الموضع المناسب في المتّجه ما لم يكن نوعه <code>‎vector&lt;bool&gt;‎</code>، وعندها سيكون من الممكن قراءته أو تعديله إذا لم يكن المتّجه ثابت.
</p>

<p>
	يختلف كل من <code>‎[]‎</code> و <code>‎at()‎</code> في أنّ العامل <code>‎[]‎</code> لا يتحقّق من الحدود بالضرورة، وذلك على خلاف <code>‎at()‎</code>. عند محاولة الوصول إلى العناصر الموجودة في الفهارس الخارجة عن الحدود، أي في حال كان <code>‎index &lt; ‎ ‎0‎</code> أو <code>‎index &gt;= size‎</code>، فسيحدث سلوك غير محدّد بالنسبة لعامل الفهرسة <code>‎[]‎</code>، في حين أنّ دالة <code>‎at()‎</code> سترفع الاعتراض <code>‎std::out_of_range‎</code>.
</p>

<p>
	<strong>ملاحظة</strong>: تستخدم الأمثلة أدناه التهيئة بنمَط C++‎ 11 لغرض التبسيط، بيد أنّه يمكن استخدام العوامل مع جميع الإصدارات، إلّا إن ذُكر C++‎ 11 صراحة.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_7" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">};</span><span class="pln">

</span><span class="com">// [] استخدام</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">[</span><span class="lit">1</span><span class="pun">];</span><span class="pln">    </span><span class="com">// تساوي 2 a </span><span class="pln">
v</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4</span><span class="pun">;</span><span class="pln">    </span><span class="com">// { 1, 4, 3 } تحتوي v </span><span class="pln">

</span><span class="com">// at() استخدام</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">at</span><span class="pun">(</span><span class="lit">2</span><span class="pun">);</span><span class="pln">    </span><span class="com">// تساوي 3 b </span><span class="pln">
v</span><span class="pun">.</span><span class="pln">at</span><span class="pun">(</span><span class="lit">2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">        </span><span class="com">//  { 1, 4, 5 } تساوي v </span><span class="pln">
</span><span class="typ">int</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">at</span><span class="pun">(</span><span class="lit">3</span><span class="pun">);</span><span class="pln">    </span><span class="com">// std::out_of_range exception رفع</span></pre>

<p>
	نظرًا لأنّ التابع <code>‎at()‎</code> يتحقّق من الحدود ويرفع اعتراضًا في حال تخطّى الفهرس لحدود المتّجه، فهو أبطأ من العامل <code>‎[]‎</code>، وهذا يجعل <code>‎[]‎</code> أنسب لمن أيقن أنّ الفهرس يقع داخل الحدود. وعمومًا فالوصول إلى عناصر المتّجهات يتم في وقت ثابت، أي أنّ الوصول إلى العنصر الأول من المتجه يستغرق نفس الوقت اللّازم للوصول إلى العنصر الثاني أو العنصر الثالث، … . انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_9" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">size</span><span class="pun">();</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    v</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	نعلم في هذا المثال أنّ متغيّرَ الفهرسِ <code>‎i‎</code> موجود دائمًا داخل الحدود، لذلك لا داعي للتحقّق ممّا إذا كان <code>‎i‎</code> داخل الحدود في كل استدعاء لعامل الفهرسة <code>‎operator[]‎</code>.
</p>

<p>
	تسمح الدالتان التابعتان <code>‎front()‎</code> و <code>‎back()‎</code> بالوصول المرجعي (reference access) إلى العنصر الأول والأخير في المتجه على الترتيب، يُستخدَم هذان الموضعان كثيرًا ويمكن أن يكونا أسهل قراءة من العامل <code>‎[]‎</code>، انظر المثال التالي حيث نشرحه بتفصيل:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_11" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">{</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pln"> </span><span class="pun">};</span></pre>

<p>
	تكون الصياغة أكثر إسهابًا في الإصدارات التي قبل C++ 11.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_13" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">front</span><span class="pun">();</span></pre>

<p>
	<code>a</code> تساوي 4، و <code>v.front</code> تكافئ <code>[v[0</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_17" style="">
<span class="pln">v</span><span class="pun">.</span><span class="pln">front</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span></pre>

<p>
	تحتوي <code>v</code> الآن على {3, 5, 6}
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_19" style="">
<span class="typ">int</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">back</span><span class="pun">();</span></pre>

<p>
	<code>b</code> تساوي 6، و <code>v.back</code> تكافئ <code>[v[v.size() - 1</code>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_21" style="">
<span class="pln">v</span><span class="pun">.</span><span class="pln">back</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">7</span><span class="pun">;</span><span class="pln">    </span></pre>

<p>
	<code>v</code> تحتوي الآن على {3, 5, 7}.
</p>

<p>
	<strong>ملاحظة</strong>: استدعاء <code>‎front()‎</code> أو <code>‎back()‎</code> على متّجه فارغ سيؤدّي إلى سلوك غير محدّد، لذا تحقّق أنّ الحاوية غير فارغة باستخدام الدالة التابعة <code>‎empty()‎</code> قبل استدعاء التابعين <code>‎front()‎</code> أو <code>‎back()‎</code>. يوضح المثال التالي استخدام <code>empty()‎</code> للتحقّق من فراغ المتّجه:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_23" style="">
<span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> sum</span><span class="pun">(</span><span class="lit">0</span><span class="pun">);</span><span class="pln">

    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">i</span><span class="pun">);</span><span class="pln"> </span><span class="com">// إنشاء وتهيئة المتّجه</span><span class="pln">

    </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">v</span><span class="pun">.</span><span class="pln">empty</span><span class="pun">())</span><span class="pln"> </span><span class="com">// التكرار على المتّجه إلى أن يصبح فارغًا</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        sum </span><span class="pun">+=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">back</span><span class="pun">();</span><span class="pln">
        v</span><span class="pun">.</span><span class="pln">pop_back</span><span class="pun">();</span><span class="pln"> </span><span class="com">// إصدار العنصر مع حذفه من المتّجه  </span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

  std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"total: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> sum </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ينشئ المثال أعلاه متجهًا يحتوي الأعداد من 1 إلى 10. ثم يُخرج عناصر المتّجها إلى أن يصبح فارغًا (باستخدام <code>empty()‎</code>) لمنع حدوث سلوك غير محدّد، ثم يُحسَب مجموع الأعداد في المتّجه ويُعرَض للمستخدم.
</p>

<p>
	<strong>الإصدار C++‎ 11</strong>
</p>

<p>
	يُعيد التابع <code>‎data()‎</code> مؤشّرًا إلى الذاكرة الخام (raw memory) التي يستخدمها المتّجه لتخزين عناصره داخليًا، ويُستخدم هذا غالبًا عند تمرير بيانات المتّجه إلى شيفرة قديمة تتوقّع مصفوفة من نمط C.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_25" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pln"> </span><span class="pun">};</span><span class="pln">    </span><span class="com">// {1, 2, 3, 4} تحتوي على  v </span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> p </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">data</span><span class="pun">();</span><span class="pln">            </span><span class="com">// يشير إلى 1 p</span><span class="pln">
</span><span class="pun">*</span><span class="pln">p </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4</span><span class="pun">;</span><span class="pln">                    </span><span class="com">// {4, 2, 3, 4} تحتوي الآن على v</span><span class="pln">
</span><span class="pun">++</span><span class="pln">p</span><span class="pun">;</span><span class="pln">                    </span><span class="com">// يشير إلى 2 p </span><span class="pln">
</span><span class="pun">*</span><span class="pln">p </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln">                    </span><span class="com">//  {4, 3, 3, 4} تحتوي الآن على v</span><span class="pln">
p</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">                </span><span class="com">//  {4, 3, 2, 4} تحتوي الآن على v</span><span class="pln">
</span><span class="pun">*(</span><span class="pln">p </span><span class="pun">+</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">                </span><span class="com">// {4, 3, 2, 1} تحتوي الآن على  v</span></pre>

<p>
	<strong>الإصدار &lt; C++‎ 11</strong>
</p>

<p>
	يمكن محاكاة التابع <code>‎data()‎</code> في الإصدارات السابقة لـ C++‎ 11 عبر استدعاء التابع <code>‎front()‎</code> وأخذ عنوان القيمة المُعادة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_27" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">(</span><span class="lit">4</span><span class="pun">);</span><span class="pln">
</span><span class="typ">int</span><span class="pun">*</span><span class="pln"> ptr </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">front</span><span class="pun">());</span><span class="pln"> </span><span class="com">// &amp;v[0] أو</span></pre>

<p>
	وينجح ذلك لأنّ المتّجهات تخزّن عناصرها دائمًا في مواقع متجاورة في الذاكرة على افتراض أنّ محتويات المتجه لا تعيد تعريف (override) المعامل الأحادي <code>‎operator&amp;‎</code>، وإلّا فسيتعيّن عليك إعادة تقديم <code>std::addressof</code> في الإصدارات السابقة للإصدار C++11. كما يُفترض أيضًا ألا يكون المتّجه فارغًا.
</p>

<h3>
	المكررات
</h3>

<p>
	تتصرف المُكرّرات (Iterators) بشكل مشابه للمؤشّرات التي تشير إلى عناصر المتّجه:
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11 </strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_29" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">{</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pln"> </span><span class="pun">};</span><span class="pln">

</span><span class="kwd">auto</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">();</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="pun">*</span><span class="pln">it</span><span class="pun">;</span><span class="pln">        </span><span class="com">// يساوي 4 i </span><span class="pln">
</span><span class="pun">++</span><span class="pln">it</span><span class="pun">;</span><span class="pln">
i </span><span class="pun">=</span><span class="pln"> </span><span class="pun">*</span><span class="pln">it</span><span class="pun">;</span><span class="pln">            </span><span class="com">// يساوي 5 i </span><span class="pln">
</span><span class="pun">*</span><span class="pln">it </span><span class="pun">=</span><span class="pln"> </span><span class="lit">6</span><span class="pun">;</span><span class="pln">            </span><span class="com">//  { 4, 6, 6 } تحتوي  v </span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> e </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">();</span><span class="pln">    </span><span class="com">//  v إلى العنصر الموجود بعد e يشير</span><span class="pln">
</span><span class="com">// يمكن استخدامه للتحقّق مما إذا بلغ المكرر نهاية المتجه</span><span class="pln">

</span><span class="pun">++</span><span class="pln">it</span><span class="pun">;</span><span class="pln">
it </span><span class="pun">==</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">();</span><span class="pln">        </span><span class="com">// يشير إلى العنصر الموجود في الموضع 2 it : خطأ</span><span class="pln">
</span><span class="pun">++</span><span class="pln">it</span><span class="pun">;</span><span class="pln">
it </span><span class="pun">==</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">();</span><span class="pln">        </span><span class="com">// true</span></pre>

<p>
	ينصّ المعيار على أنّ المكرّرات <code>‎std::vector&lt;T&gt;‎</code> هي مؤشّرات في الواقع من النوع <code>‎T*‎</code>، لكنّ معظم المكتبات القياسية لا تطبّق ذلك من أجل تحسين رسائل الخطأ ورصد الشيفرات غير المحمولة، ولتجهيز المُكرّرات بعمليات التحقّق من الأخطاء في عمليات البناء غير المُصدَرة (non-release builds). ثمّ بعد ذلك يمكن حذف الصنف الذي يغلّف المؤشّر الأساسي في عمليات البناء المُصدَرة (release builds) من أجل تحسين الشيفرة.
</p>

<p>
	تستطيع استدامة مرجع أو مؤشّر يشير إلى أحد عناصر المتّجه لاستخدامه للوصول غير المباشر، وتظل هذه المراجع أو المؤشّرات التي تشير إلى عناصر المتجه مستقرة كما يظلّ الوصول ممكنًا إلّا في حال أضفت أو أزلت عناصر قبل موضع ذلك العنصر من المتّجه أو فيه، أو في حال تغيير سعة المتّجه. يكافئ هذا قواعد إبطال [المُكرّرات](رابط الفصل 9).
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11 </strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_31" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="com">// يشير إلى 2 p</span><span class="pln">
</span><span class="typ">int</span><span class="pun">*</span><span class="pln"> p </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">data</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">        

</span><span class="com">// ستؤدّي إلى سلوك غير محدّد *p أصبح غير صالح، محاولة الوصول إلى p</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln">    

</span><span class="com">// يشير إلى 1 p </span><span class="pln">
p </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">data</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">    

</span><span class="com">// ستؤدّي إلى سلوك غير محدّد *p أصبح غير صالح، محاولة الوصول إلى p    </span><span class="pln">
v</span><span class="pun">.</span><span class="pln">reserve</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln">        

</span><span class="com">// يشير إلى 1 p</span><span class="pln">
p </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">data</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">    

</span><span class="com">// ستؤدي إلى سلوك غير محدّد *p أصبح غير صالح، محاولة الوصول إلى p    </span><span class="pln">
v</span><span class="pun">.</span><span class="pln">erase</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">());</span><span class="pln">        </span></pre>

<h2>
	تهيئة متجه
</h2>

<p>
	يمكن تهيئة المتّجهات بعدة طرق أثناء التصريح عنها:
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11 </strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_33" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">};</span><span class="pln">        </span><span class="com">//  {1, 2, 3}</span><span class="pln">

</span><span class="com">// std::vector&lt;int&gt; v(3, 6) مختلفة عن</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">{</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pln"> </span><span class="pun">};</span><span class="pln">        </span><span class="com">// {3, 6}</span><span class="pln">

</span><span class="com">// std::vector&lt;int&gt; v{3, 6} in C++11 مختلفة عن</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v</span><span class="pun">(</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pun">);</span><span class="pln">        </span><span class="com">// {6, 6, 6}</span><span class="pln">

std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v</span><span class="pun">(</span><span class="lit">4</span><span class="pun">);</span><span class="pln">        </span><span class="com">// {0, 0, 0, 0}</span></pre>

<p>
	يمكن تهيئة المتجه من حاوية أخرى عبر عدّة طرق:
</p>

<ul>
<li>
		النسخ (من متّجه آخر)، ووهذا ينسخ البيانات من <code>‎v2‎</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_35" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">(</span><span class="pln">v2</span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v </span><span class="pun">=</span><span class="pln"> v2</span><span class="pun">;</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11 </strong>
</p>

<ul>
<li>
		النّقل (من متّجه آخر)، والذي ينقل البيانات من <code>‎v2‎</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_37" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">v2</span><span class="pun">));</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">v2</span><span class="pun">);</span></pre>

<ul>
<li>
		استخدام مُكرّر (نطاقي) لنسخ العناصر إلى <code>‎v‎</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_39" style="">
<span class="com">// من متّجه آخر</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v</span><span class="pun">(</span><span class="pln">v2</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v2</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">3</span><span class="pun">);</span><span class="pln">        </span><span class="com">// {v2[0], v2[1], v2[2]}</span><span class="pln">

</span><span class="com">// من مصفوفة</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> z</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v</span><span class="pun">(</span><span class="pln">z</span><span class="pun">,</span><span class="pln"> z </span><span class="pun">+</span><span class="pln"> </span><span class="lit">3</span><span class="pun">);</span><span class="pln">                </span><span class="com">// {1, 2, 3}</span><span class="pln">

</span><span class="com">// من قائمة</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">list</span><span class="str">&lt;int&gt;</span><span class="pln"> list1</span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v</span><span class="pun">(</span><span class="pln">list1</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> list1</span><span class="pun">.</span><span class="pln">end</span><span class="pun">());</span><span class="pln">        </span><span class="com">// {1, 2, 3}</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11 </strong>
</p>

<ul>
<li>
		النقل عبر مكرّر باستخدام <code>‎std::make_move_iterator‎</code>، والذي ينقل العناصر إلى <code>‎v‎</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_41" style="">
<span class="com">// من متّجه آخر</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">make_move_iterator</span><span class="pun">(</span><span class="pln">v2</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">()),</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">make_move_iterator</span><span class="pun">(</span><span class="pln">v2</span><span class="pun">.</span><span class="pln">end</span><span class="pun">());</span><span class="pln">
</span><span class="com">// من قائمة</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">list</span><span class="str">&lt;int&gt;</span><span class="pln"> list1</span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">make_move_iterator</span><span class="pun">(</span><span class="pln">list1</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">()),</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">make_move_iterator</span><span class="pun">(</span><span class="pln">list1</span><span class="pun">.</span><span class="pln">end</span><span class="pun">()));</span></pre>

<ul>
<li>
		يمكن إعادة تهيئة المتجه بعد إنشائه باستخدام التابع <code>‎assign()‎</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_43" style="">
<span class="pln">v</span><span class="pun">.</span><span class="pln">assign</span><span class="pun">(</span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">100</span><span class="pun">);</span><span class="pln">                </span><span class="com">// {100, 100, 100, 100}</span><span class="pln">

v</span><span class="pun">.</span><span class="pln">assign</span><span class="pun">(</span><span class="pln">v2</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v2</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">3</span><span class="pun">);</span><span class="pln">    </span><span class="com">// {v2[0], v2[1], v2[2]}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> z</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">assign</span><span class="pun">(</span><span class="pln">z </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> z </span><span class="pun">+</span><span class="pln"> </span><span class="lit">4</span><span class="pun">);</span><span class="pln">            </span><span class="com">// {2, 3, 4}</span></pre>

<h2>
	حذف العناصر
</h2>

<ul>
<li>
		حذف العنصر الأخير:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_45" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">pop_back</span><span class="pun">();</span><span class="pln"> </span><span class="com">// {1, 2}</span></pre>

<ul>
<li>
		حذف جميع العناصر:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_47" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">clear</span><span class="pun">();</span><span class="pln"> </span><span class="com">// أصبحت فارغة v</span></pre>

<ul>
<li>
		حذف العنصر الموجود عند فهرس معيّن:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_49" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">erase</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">3</span><span class="pun">);</span><span class="pln"> </span><span class="com">// {1, 2, 3, 5, 6}</span></pre>

<p>
	ملاحظة: عند حذف أي عنصر من المتّجه -باستثناء العنصر الأخير- فيجب نسخ جميع العناصر الموجودة بعد العنصر المحذوف أو نقلها لسدّ الفجوة التي خلّفتها عملية الحذف.
</p>

<ul>
<li>
		حذف جميع العناصر الموجودة في نطاق معيّن:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_51" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">erase</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">5</span><span class="pun">);</span><span class="pln"> </span><span class="com">// {1, 6} أصبحت تساوي  v</span></pre>

<p>
	ملاحظة: التوابع المذكورة أعلاه لا تغيّر سعة المتّجه، وإنّما تغير حجمه وحسب (انظر أسفله في فقرة حجم المتّجهات وسعتها).
</p>

<p>
	يُستخدم تابع <code>erase</code> -الذي يزيل مجموعة من العناصر- كجزء من مقاربة <a data-ss1617022526="1" href="https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom" rel="external nofollow">الحذف والنقل</a>، أي أنّه في البداية ينقل التابع <code>‎std::remove‎</code> بعض العناصر إلى نهاية المتّجه، ثم يقطع التابع <code>‎erase‎</code> تلك العناصر. هذه العملية مكلّفة نسبيًا إلّا في حال الفهرس الأخير، لأنّه يجب نقل جميع العناصر بعد القطعة المحذوفة إلى مواضع جديدة. أما إن كنت تعمل على تطبيقات تتطلب سرعة كبيرة في إزالة العناصر من الحاويات، فالأفضل استخدام القوائم (lists).
</p>

<ul>
<li>
		حذف العناصر بالقيمة:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_53" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> value_to_remove </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">erase</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">remove</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> value_to_remove</span><span class="pun">),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">());</span><span class="pln">
</span><span class="com">// {1, 1, 3, 3} أصبحت تساوي  v</span></pre>

<ul>
<li>
		حذف العناصر التي تحقّق شرطًا معيّنا. في المثال التالي، تحتاج <code>std::remove_if</code> إلى دالة تأخذ متجهًا كوسيط، وتعيد <code>true</code> إن كان يجب حذف العنصر:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_55" style="">
<span class="kwd">bool</span><span class="pln"> _predicate</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&amp;</span><span class="pln"> element</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">element </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">);</span><span class="pln"> </span><span class="com">// ستُحذف العناصر الأكبر من 3</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">erase</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">remove_if</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> _predicate</span><span class="pun">),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">());</span><span class="pln"> </span><span class="com">// {1, 2, 3} أصبحت  v</span></pre>

<ul>
<li>
		حذف العناصر عبر تعابير لامدا دون إنشاء دالّة شرطية إضافية:
	</li>
</ul>
<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_57" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">erase</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">remove_if</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> </span><span class="pun">[](</span><span class="kwd">auto</span><span class="pun">&amp;</span><span class="pln"> element</span><span class="pun">){</span><span class="kwd">return</span><span class="pln"> element </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;}</span><span class="pln"> </span><span class="pun">),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">());</span></pre>

<ul>
<li>
		حذف العناصر التي تحقّق شرطًا معيّنا في حلقة:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_59" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="typ">iterator</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">it </span><span class="pun">!=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">condition</span><span class="pun">)</span><span class="pln">
        it </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">erase</span><span class="pun">(</span><span class="pln">it</span><span class="pun">);</span><span class="pln"> </span><span class="com">// v إلى العنصر الموالي في 'it' بعد الحذف، سيشير</span><span class="pln">
    </span><span class="kwd">else</span><span class="pln">
        </span><span class="pun">++</span><span class="pln">it</span><span class="pun">;</span><span class="pln"> </span><span class="com">// يشير إلى العنصر الموالي يدويا  'it' جعل   </span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لذا يجب عليك التفكير في استخدام طريقة أخرى عند تكرار الحذف في الحلقات، بما أن من الضروري عدم زيادة <code>‎it‎</code> في حال حذف عنصر، فالتابع <code>‎remove_if‎</code> أكثر كفاءة وفعالية.
</p>

<ul>
<li>
		حذف العناصر التي تحقّق شرطًا معيّنا في حلقة عكسية:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_61" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">{</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">typedef</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">reverse_iterator rev_itr</span><span class="pun">;</span><span class="pln">
rev_itr it </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">rbegin</span><span class="pun">();</span><span class="pln">

</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">it </span><span class="pun">!=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">rend</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">        </span><span class="com">// v بعد الحلقة، لن تبقى إلا الأصفار في</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> value </span><span class="pun">=</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> it</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">value</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="pun">++</span><span class="pln">it</span><span class="pun">;</span><span class="pln">
        it </span><span class="pun">=</span><span class="pln"> rev_itr</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">erase</span><span class="pun">(</span><span class="pln">it</span><span class="pun">.</span><span class="pln">base</span><span class="pun">()));</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln">
        </span><span class="pun">++</span><span class="pln">it</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هذه بعض الملاحظات بخصوص الحلقة السابقة:
</p>

<ul>
<li>
		إن كان المكرّر العكسي <code>‎it‎</code> يشير إلى عنصر ما، فإنّ التابع <code>‎<a data-ss1617022526="1" href="https://en.cppreference.com/w/cpp/iterator/reverse_iterator/base" rel="external nofollow">base‎</a></code> سيعيد المُكرّر العادي (غير العكسي) الذي يشير إلى نفس العنصر.
	</li>
	<li>
		يمحو التابع <code>vector::erase(iterator)‎</code> العنصر المشار إليه من قبل المكرّر، ويعيد مكرّرًا إلى العنصر الذي يتبع العنصر المُعطى.
	</li>
	<li>
		ينشئ التابع <code>reverse_iterator::reverse_iterator(iterator)‎</code> مكرّرًا عكسيًّا من مُكرّر ما.
	</li>
</ul>
<p>
	هذا يعني أن السطر <code>‎it = rev_itr(v.erase(it.base()))‎</code> يقول: أخذ المُكرّر العكسي <code>‎it‎</code>، واجعل <code>‎v‎</code> تمحو العنصر الذي يشير إليه مُكرّرها العادي؛ ثم خذ المُكرِّر الناتج، وأنشئ مكرّرًا عكسيًّا منه، ثم عيّنه إلى المكرّر العكسي <code>‎it‎</code>.
</p>

<p>
	لن يؤدي استخدام <code>‎v.clear()‎</code> لحذف جميع عناصر المتّجه إلى تحرير الذاكرة، إذ تظل سعة المتّجه دون تغيير. ولتحرير مساحة الذاكرة، استخدم:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_64" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pun">().</span><span class="pln">swap</span><span class="pun">(</span><span class="pln">v</span><span class="pun">);</span></pre>

<p>
	الإصدار ≥ C++‎ 11
</p>

<p>
	يحرّر التابع <code>‎shrink_to_fit‎</code> سعة المتّجه غير المستخدم، لكنه لا يضمن تحرير المساحدة بالضرورة، رغم أن أغلب التطبيقات (Implementations) الحالية تضمن ذلك.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_66" style="">
<span class="pln">v</span><span class="pun">.</span><span class="pln">shrink_to_fit</span><span class="pun">();</span></pre>

<h2>
	التكرار على المتجهات
</h2>

<p>
	تُعرّف <code>‎v‎</code> في الأمثلة التالية على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_68" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">;</span></pre>

<h3>
	التكرار الأمامي
</h3>

<p>
	الإصدار ≥ C++‎ 11 حلقة <code>for</code> نطاقية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_70" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pun">&amp;</span><span class="pln"> value</span><span class="pun">:</span><span class="pln"> v</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	استخدام حلقة <code>for</code> مع مكرِّر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_72" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">begin</span><span class="pun">(</span><span class="pln">v</span><span class="pun">);</span><span class="pln"> it </span><span class="pun">!=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">end</span><span class="pun">(</span><span class="pln">v</span><span class="pun">);</span><span class="pln"> </span><span class="pun">++</span><span class="pln">it</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln">it </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	استخدام خوارزمية <code>for_each</code> باستخدام دالة أو صنف كائن دالي (functor):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_74" style="">
<span class="kwd">void</span><span class="pln"> fun</span><span class="pun">(</span><span class="typ">int</span><span class="pln">
    </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> value</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">for_each</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">begin</span><span class="pun">(</span><span class="pln">v</span><span class="pun">),</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">end</span><span class="pun">(</span><span class="pln">v</span><span class="pun">),</span><span class="pln"> fun</span><span class="pun">);</span></pre>

<p>
	استخدام خوارزمية <code>for_each</code> باستخدام لامدا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_76" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">for_each</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">begin</span><span class="pun">(</span><span class="pln">v</span><span class="pun">),</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">end</span><span class="pun">(</span><span class="pln">v</span><span class="pun">),</span><span class="pln"> </span><span class="pun">[](</span><span class="typ">int</span><span class="pln">
    </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> value</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	الإصدار <c> استخدام حلقة <code>for</code> مع مكرِّر:</c>++‎&gt;
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_78" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">for_each</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">rbegin</span><span class="pun">(</span><span class="pln">v</span><span class="pun">),</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">rend</span><span class="pun">(</span><span class="pln">v</span><span class="pun">),</span><span class="pln"> </span><span class="pun">[](</span><span class="kwd">auto</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> value</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln">it </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	استخدام حلقة <code>for</code> مع فهرس:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_80" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">size</span><span class="pun">();</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> v</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	التكرار في الاتجاه العكسي
</h3>

<p>
	<strong>الإصدار ≥ C++‎ 14</strong>
</p>

<p>
	لا توجد طريقة معيارية لاستخدام حلقة <code>for</code> النطاقية هنا، وإنما لدينا بدائل لها، انظر ما يلي: استخدام خوارزمية <code>for_each</code>، لاحظ استخدام تعبير لامدا للتوضيح، لكن اعلم أنك تستطيع استخدام صنف كائن دالّي (functor):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_82" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">for_each</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">rbegin</span><span class="pun">(</span><span class="pln">v</span><span class="pun">),</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">rend</span><span class="pun">(</span><span class="pln">v</span><span class="pun">),</span><span class="pln"> </span><span class="pun">[](</span><span class="kwd">auto</span><span class="pln">
    </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> value</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	استخدام حلقة <code>for</code> مع مكرر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_84" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> rit </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">rbegin</span><span class="pun">(</span><span class="pln">v</span><span class="pun">);</span><span class="pln"> rit </span><span class="pun">!=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">rend</span><span class="pun">(</span><span class="pln">v</span><span class="pun">);</span><span class="pln"> </span><span class="pun">++</span><span class="pln">rit</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln">rit </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	استخدام حلقة <code>for</code> مع فهرس:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_86" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">size</span><span class="pun">();</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> v</span><span class="pun">[</span><span class="pln">v</span><span class="pun">.</span><span class="pln">size</span><span class="pun">()</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	رغم أنّه لا يوجد تابع مُضمّن يستخدم حلقة <code>for</code> النطاقية للتكرار العكسي، إلا أننا نستطيع استخدام التابعين <code>‎begin()‎</code> و <code>‎end()‎</code> للحصول على المُكرّرات، ومن ثم محاكاة ذلك باستخدام كائن مُغلّف (wrapper) للحصول على النتائج التي نريد.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 14</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_88" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> C </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">ReverseRange</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        C c</span><span class="pun">;</span><span class="pln"> </span><span class="com">// يمكن أن تكون مرجعا أو نسخة في حال كانت القيمة الأصلية مؤقتة</span><span class="pln">
        </span><span class="typ">ReverseRange</span><span class="pun">(</span><span class="pln">C</span><span class="pun">&amp;&amp;</span><span class="pln"> cin</span><span class="pun">):</span><span class="pln"> c</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">forward </span><span class="pun">&lt;</span><span class="pln"> C </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">cin</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
        </span><span class="typ">ReverseRange</span><span class="pun">(</span><span class="typ">ReverseRange</span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
        </span><span class="typ">ReverseRange</span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="typ">ReverseRange</span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">delete</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">auto</span><span class="pln"> begin</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">rbegin</span><span class="pun">(</span><span class="pln">c</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">auto</span><span class="pln"> end</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">rend</span><span class="pun">(</span><span class="pln">c</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> C </span><span class="pun">&gt;</span><span class="pln">
   </span><span class="typ">ReverseRange</span><span class="pun">&lt;</span><span class="pln">C</span><span class="pun">&gt;</span><span class="pln"> make_ReverseRange</span><span class="pun">(</span><span class="pln">C</span><span class="pun">&amp;&amp;</span><span class="pln"> c</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="pln">std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="pln">C</span><span class="pun">&gt;(</span><span class="pln">c</span><span class="pun">)};}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v </span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">,</span><span class="lit">3</span><span class="pun">,</span><span class="lit">4</span><span class="pun">};</span><span class="pln">
    </span><span class="kwd">for</span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> value</span><span class="pun">:</span><span class="pln"> make_ReverseRange</span><span class="pun">(</span><span class="pln">v</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	فرض العناصر الثابتة
</h3>

<p>
	منذ الإصدار C++‎ 11، يسمح لك التابعان <code>‎cbegin()‎</code> و <code>‎cend()‎</code> بالحصول على مُكرّر ثابت (constant iterator) لمُتجه حتى لو كان المتّجه غير ثابت، وتسمح المكرّرات الثابتة بقراءة محتويات المتّجه لكن لا تسمح بتعديلها، وهو أمر مفيد لفرض الثباتية (const correctness).
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11 </strong>
</p>

<p>
	التكرار الأمامي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_90" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> pos </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">cbegin</span><span class="pun">();</span><span class="pln"> pos </span><span class="pun">!=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">cend</span><span class="pun">();</span><span class="pln"> </span><span class="pun">++</span><span class="pln">pos</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// type of pos is vector&lt;T&gt;::const_iterator</span><span class="pln">
    </span><span class="com">// *pos = 5; // Compile error - can't write via const iterator</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	التكرار العكسي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_92" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> pos </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">crbegin</span><span class="pun">();</span><span class="pln"> pos </span><span class="pun">!=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">crend</span><span class="pun">();</span><span class="pln"> </span><span class="pun">++</span><span class="pln">pos</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// type of pos is vector&lt;T&gt;::const_iterator</span><span class="pln">
    </span><span class="com">// *pos = 5; // Compile error - can't write via const iterator</span><span class="pln">
</span><span class="pun">}</span></pre>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_94" style="">
<span class="com">// Functor::operand()(T&amp;) تتوقُّع</span><span class="pln">
for_each</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> </span><span class="typ">Functor</span><span class="pun">());</span><span class="pln">

</span><span class="com">// Functor::operand()(const T&amp;) تتوقُّع</span><span class="pln">
for_each</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">cbegin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">cend</span><span class="pun">(),</span><span class="pln"> </span><span class="typ">Functor</span><span class="pun">())</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 17</strong>
</p>

<p>
	يوسّع <a data-ss1617022526="1" href="https://en.cppreference.com/w/cpp/utility/as_const" rel="external nofollow">as_const</a> هذا إلى التكرار النطاقي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_96" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> e </span><span class="pun">:</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">as_const</span><span class="pun">(</span><span class="pln">v</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> e </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هذا سهل التنفيذ في الإصدارات السابقة لـ C++‎:
</p>

<p>
	<strong>الإصدار ≥ C++‎ 14</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_99" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">constexpr</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">add_const_t</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;&amp;</span><span class="pln"> as_const</span><span class="pun">(</span><span class="pln">T</span><span class="pun">&amp;</span><span class="pln"> t</span><span class="pun">)</span><span class="pln"> noexcept </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> t</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span></pre>

<h3>
	ملاحظات حول الكفاءة
</h3>

<p>
	نظرًا لأنّ الصنف <code>‎std::vector‎</code> هو في الأساس صنف يدير مصفوفةً ديناميكية ذات ذاكرة متجاورة، فسَينطبق المبدأ نفسه المُوضّح هنا على متّجهات C++‎، وسيكون الوصول إلى محتوى المتّجه عبر الفهرس أسهل عند اتّباع مبدأ ترتيب الصفوف الرئيسية (row-major order principle). لا شك أن كل محاولة وصول إلى المتّجه ستؤدّي إلى وضع محتوى إدارتها في ذاكرة التخزين المؤقت أيضًا، لكن الفرق في الأداء عند التكرار على متجه صغير ومهمل إن قورن بمصفوفة خام، <a data-ss1617022526="1" href="https://stackoverflow.com/questions/3664272/is-stdvector-so-much-slower-than-plain-arrays" rel="external nofollow">انظر هذه المناقشات -بالإنجليزية- عن الأمر للتوضيح</a> و<a data-ss1617022526="1" href="https://stackoverflow.com/questions/381621/using-arrays-or-stdvectors-in-c-whats-the-performance-gap" rel="external nofollow">هذه أيضًا</a>). وعليه ينطبق مبدأ الكفاءة نفسه الخاص بالمصفوفات الخام في C على المتّجهات في C++‎.
</p>

<h2>
	المتجه ‎vector<bool>‎: الاستثناء الكبير</bool>
</h2>

<p>
	ينصّ المعيار (قسم 23.3.7) على أن يُوفَّر تخصيص للمتّجه <code>‎vector&lt;bool&gt;‎</code>، من أجل تحسين إدارة الذاكرة بترشيد تخزين القيم البوليانية <code>‎bool‎</code> بحيث يأخذ كل منها بتّة واحدة فقط. ونظرًا لأنّه لا يمكن معالجة البتات في C++‎، فهذا يعني أنّ العديد من مُتطلبات المتّجهات العادية لن تنطبق على <code>‎vector&lt;bool&gt;‎</code>:
</p>

<ul>
<li>
		<p>
			لا يلزم أن تكون البيانات المُخزّنة متجاورة، لذا لا يمكن تمرير متجه <code>‎vector&lt;bool&gt;‎</code> إلى واجهة برمجية للغة C تتوقّع مصفوفة ذات قيم منطقية.
		</p>
	</li>
	<li>
		<p>
			لا يعيد التابع <code>‎at()‎</code> ولا المعامل <code>‎operator[]‎</code> ولا تحصيل المُكرّرات مرجعًا إلى قيمة منطقية، بل تعيد كائنًا وكيلًا (proxy object) يحاكي بشكل تقريبي مرجعًا إلى <code>‎bool‎</code> من خلال زيادة تحميل عامل إسناده، فقد لا تكون الشيفرة التالية صالحة بالنسبة للمتّجهات من النوع <code>‎std::vector&lt;bool&gt;‎</code> لأنّ تحصيل المُكرّر لا يُعيد مرجعًا:
		</p>
	</li>
</ul>
<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_101" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;bool&gt;</span><span class="pln"> v </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="kwd">true</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">b</span><span class="pun">:</span><span class="pln"> v</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="com">// خطأ</span></pre>

<p>
	وبالمثل، لا يمكن استخدام الدوالّ التي تتوقّع وسيطَا من النوع <code>‎bool&amp;‎</code> مع النتيجة المُعادة من قبل <code>‎operator []‎</code> أو <code>‎at()‎</code> عند تطبيقها على متّجه منطقيّ <code>vector&lt;bool&gt;‎</code>، أو مع نتيجة تحصيل المكرّر الخاص بها:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_103" style="">
<span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">bool</span><span class="pun">&amp;</span><span class="pln"> b</span><span class="pun">);</span><span class="pln">
f</span><span class="pun">(</span><span class="pln">v</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]);</span><span class="pln"> </span><span class="com">// خطأ</span><span class="pln">
f</span><span class="pun">(*</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">());</span><span class="pln"> </span><span class="com">// خطأ</span></pre>

<p>
	يتعلّق تطبيق المتجه <code>‎std::vector&lt;bool&gt;‎</code> بكل من المُصرّف والمعمارية، ويُطبَّق التخصيص الخاصّ بهذا النوع من المتّجهات عن طريق تعبئة <code>‎n‎</code> قيمة منطقية في أقل قسم من الذاكرة، وهنا تمثّل <code>‎n‎</code> الحجم لأقل ذاكرة يمكن معالجتها بالبِتّْ، والتي تساوي في معظم الأنظمة الحديثة بايت واحد، أو 8 بتّات. هذا يعني أنّ بايت واحد يمكنه تخزين 8 قيم منطقية، وهذا أفضل من التنفيذ التقليدي حيث تُخزّن كل قيمة منطقية في بايت واحد من الذاكرة.
</p>

<p>
	ملاحظة: يُظهر المثال التالي القيم المحتملة للبايتات في الصيغة التقليدية مقابل الصيغة المُحسّنة، لن يكون هذا صحيحًا في جميع الأنظمة، لكنّه لغرض توضيح الفرق بين الطريقتين. في الأمثلة أدناه، يُمثّل البايت على هيئة [x، x، x، x، x، x، x، x].
</p>

<p>
	الطريقة التقليدية: تخزين 8 قيم بوليانية في المتجه <code>std::vector&lt;char&gt;‎</code>:
</p>

<p>
	الإصدار ≥ C++‎ 11
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_105" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;char&gt;</span><span class="pln"> trad_vect </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="kwd">true</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">};</span></pre>

<p>
	التمثيل البتّي (Bitwise representation):
</p>

<pre class="ipsCode" id="ips_uid_8850_110">
[0,0,0,0,0,0,0,1], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,1], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,1], [0,0,0,0,0,0,0,1]
</pre>

<p>
	المُخصّص: تخزين 8 قيم بوليانية في المتجه <code>std::vector&lt;bool&gt;‎</code>:
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_108" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;bool&gt;</span><span class="pln"> optimized_vect </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="kwd">true</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">};</span></pre>

<p>
	التمثيل البتّي:
</p>

<pre class="ipsCode" id="ips_uid_8850_112">
[1,0,0,0,1,0,1,1]
</pre>

<p>
	لاحظ في المثال أعلاه، أنّه في النسخة التقليدية للمتجه <code>‎std::vector&lt;bool&gt;‎</code>، ستحتل 8 قيم بوليانية 8 بايتات من الذاكرة، بينما في النسخة المُحسّنة من <code>‎std::vector&lt;bool&gt;‎</code>، فإنها تحتل بايت واحد فقط من الذاكرة. وهذا تحسّن كبير في استخدام الذاكرة. إن احتجت إلى تمرير متجه <code>‎vector&lt;bool&gt;‎</code> إلى واجهة برمجية من نمَط C فقد تحتاج إلى نسخ القيم إلى <a data-ss1617022526="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-7-%D8%A7%D9%84%D9%85%D8%B5%D9%81%D9%88%D9%81%D8%A7%D8%AA-%D9%81%D9%8A-cpp-r891/" rel="">مصفوفة</a>، أو البحث عن طريقة أفضل لاستخدام الواجهة البرمجية (<abbr title="Application Programming Interface | واجهة برمجية">API</abbr>) في حال كان الأداء واستخدام الذاكرة غير فعّالين.
</p>

<h2>
	إدراج العناصر
</h2>

<p>
	إلحاق عنصر بنهاية المتجه عن طريق النسخ أو النقل:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_114" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Point</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">double</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">Point</span><span class="pun">(</span><span class="kwd">double</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> y</span><span class="pun">):</span><span class="pln"> x</span><span class="pun">(</span><span class="pln">x</span><span class="pun">),</span><span class="pln"> y</span><span class="pun">(</span><span class="pln">y</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Point</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Point</span><span class="pln"> p</span><span class="pun">(</span><span class="lit">10.0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2.0</span><span class="pun">);</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">p</span><span class="pun">);</span><span class="pln"> </span><span class="com">// في المتجه p نسخ</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	إلحاق عنصر بنهاية المتجه عبر إنشاء العنصر فوريًّا: تُمرر الوسائط إلى المنشئ الخاص بالنوع المعطى، وينشأ الكائن في المتجه لتجنب النسخ.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_116" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="pun">&lt;</span><span class="typ">Point</span><span class="pun">&gt;</span><span class="pln"> v</span><span class="pun">;</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">emplace_back</span><span class="pun">(</span><span class="lit">10.0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2.0</span><span class="pun">);</span><span class="pln"> </span></pre>

<p>
	لاحظ أنّ المتّجهات ليس لها تابع <code>‎push_front()‎</code> لأسباب تتعلق بالأداء، وتؤدّي إضافة عنصر إلى بداية المتجه إلى نقل جميع عناصره، وإن أردت إدراج العناصر بشكل متكرر في بداية الحاوية فالأفضل استخدام النوع <code>‎std::list‎</code> أو <code>‎std::deque‎</code>.
</p>

<p>
	إدراج عنصر في أيّ موضع في المتجه:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_118" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> </span><span class="lit">9</span><span class="pun">);</span><span class="pln"> </span><span class="com">// {9, 1, 2, 3} تحتوي الآن على v </span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	إدراج عنصر في أيّ موضع من المتجه عن طريق إنشاء العنصر فوريًّا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_120" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">emplace</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">()+</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pun">);</span><span class="pln"> </span><span class="com">// {1, 9, 2, 3} تحتوي الآن على v</span></pre>

<p>
	إدراج متجه آخر في أيّ موضع في المتجه:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_122" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">(</span><span class="lit">4</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 0, 0, 0, 0 تحتوي</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v2</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 10, 10 تحتوي</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">()+</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> v2</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v2</span><span class="pun">.</span><span class="pln">end</span><span class="pun">());</span><span class="pln"> </span><span class="com">// 0, 0, 10, 10, 0, 0 تحتوي</span></pre>

<p>
	إدراج <a data-ss1617022526="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-7-%D8%A7%D9%84%D9%85%D8%B5%D9%81%D9%88%D9%81%D8%A7%D8%AA-%D9%81%D9%8A-cpp-r891/" rel="">مصفوفة</a> في أيّ موضع من المتجه:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_124" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">(</span><span class="lit">4</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 0, 0, 0, 0 </span><span class="pln">
</span><span class="typ">int</span><span class="pln"> a </span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">};</span><span class="pln"> </span><span class="com">// 1, 2, 3 </span><span class="pln">
v</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">()+</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> a</span><span class="pun">+</span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">a</span><span class="pun">)/</span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">a</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]));</span><span class="pln"> </span><span class="com">// 0, 1, 2, 3, 0, 0, 0 </span></pre>

<p>
	استخدم التابع <code>‎reserve()‎</code> قبل إدراج عدّة عناصر دفعة واحدة إن كان حجم المتّجه الناتج معروفًا مُسبقًا، لتجنّب تكرير عمليّات إعادة تخصيص الذاكرة (انظر فقرة حجم المتّجهات وسعتها أدناه):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_126" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v</span><span class="pun">;</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">reserve</span><span class="pun">(</span><span class="lit">100</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">100</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i</span><span class="pun">)</span><span class="pln">
    v</span><span class="pun">.</span><span class="pln">emplace_back</span><span class="pun">(</span><span class="pln">i</span><span class="pun">);</span></pre>

<p>
	لا تستدع التابع <code>‎resize()‎</code> في هذه الحالة، وإلا فستنشئ عن غير قصد متجه يحتوي 200 عنصر، وستوضع القيم التي تريدها في المئة عنصر الأخيرة من المتجه.
</p>

<h2>
	استخدام المتجهات كمصفوفات من نمط C
</h2>

<p>
	هناك عدّة أسباب لاستخدام المتّجهات كمصفوفات من نمَط C، كالتوافق مع مكتبات C مثلًا، وهذا ممكن لأنّ عناصر المتجه مُخزّنة في مواضع متجاورة.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_128" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pun">*</span><span class="pln"> p </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">data</span><span class="pun">();</span></pre>

<p>
	يجوز تطبيق التابع <code>‎.data()‎</code> على المتّجهات الفارغة أيضًا على عكس الحلول السابقة القائمة على معايير C++‎ (انظر أدناه)، إذ أنّه لن يتسبّب في سلوك غير محدّد في هذه الحالة.
</p>

<p>
	كان عليك قبل الإصدار C++‎ 11 أن تأخذ عنوان العنصر الأوّل في المتجه للحصول على مؤشّر مكافئ، وإذا لم يكن المتجه فارغًا، فإنّ هذين التابعين سيكونان متكافئين:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_130" style="">
<span class="typ">int</span><span class="pun">*</span><span class="pln"> p </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">v</span><span class="pun">[</span><span class="lit">0</span><span class="pun">];</span><span class="pln"> 
</span><span class="typ">int</span><span class="pun">*</span><span class="pln"> p </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">v</span><span class="pun">.</span><span class="pln">front</span><span class="pun">();</span><span class="pln"> </span><span class="com">// مؤشّر إلى العنصر الأول</span></pre>

<p>
	ملاحظة: إذا كانت المتجه فارغًا، فلا يمكن استخدام <code>‎v[0]‎</code> و <code>‎v.front()‎</code> لأنّ سلوكهما سيكون غير محدّد.
</p>

<p>
	عند تخزين العنوان الأساسي لبيانات المتجه، لاحظ أنّ العديد من العمليات (مثل <code>‎push_back‎</code> و <code>‎resize‎</code> وغيرها) يمكن أن تغيّر مواضع بيانات المتّجة في الذاكرة، وذلك سيبطل مؤشّرات البيانات السابقة. مثلا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_132" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pun">*</span><span class="pln"> p </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">data</span><span class="pun">();</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">resize</span><span class="pun">(</span><span class="lit">42</span><span class="pun">);</span><span class="pln"> </span><span class="com">// صالحا p تغيّر مواضع الذاكرة داخليا، لذا لم يعد</span></pre>

<h2>
	إيجاد عنصر في متجه
</h2>

<p>
	يمكن استخدام الدالّة <code>‎std::find‎</code>، المُعرّفة في الترويسة <algorithm>، لإيجاد عنصر في متجه، ويستخدم التابعُ <code>std::find</code> المعامل<code>‎operator==‎</code> للتحقّق من تساوي العناصر، ويعيد مكرّرًا إلى أول عنصر في النطاق يساوي القيمة المبحوث عنها. </algorithm></p>

<p>
	إذا لم يُعثر على عنصر يحقّق ذلك، فإنّ التابع <code>‎std::find‎</code> سيُعيد <code>‎std::vector::end‎</code> (أو <code>‎std::vector::cend‎</code> إذا كانت المتجه ثابتًا <code>‎const‎</code>).
</p>

<p>
	<strong>الإصدار  &lt; C++11</strong><br><c></c>++‎&gt;
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_134" style="">
<span class="kwd">static</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> arr</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">};</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v </span><span class="pun">(</span><span class="pln">arr</span><span class="pun">,</span><span class="pln"> arr </span><span class="pun">+</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">arr</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">arr</span><span class="pun">[</span><span class="lit">0</span><span class="pun">])</span><span class="pln"> </span><span class="pun">);</span><span class="pln">

std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pun">::</span><span class="typ">iterator</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">find</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> </span><span class="lit">4</span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pun">::</span><span class="pln">difference_type index </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">distance</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> it</span><span class="pun">);</span><span class="pln">
</span><span class="com">// إلى العنصر الثاني في المتجه `it` يشير</span><span class="pln">

std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="typ">iterator</span><span class="pln"> missing </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">find</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> </span><span class="lit">10</span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">difference_type index_missing </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">distance</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> missing</span><span class="pun">);</span><span class="pln">
</span><span class="com">// تساوي  5 index_missing و  v.end() تساوي `missing` </span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_136" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v </span><span class="pun">{</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">};</span><span class="pln">

</span><span class="kwd">auto</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">find</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> </span><span class="lit">4</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> index </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">distance</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> it</span><span class="pun">);</span><span class="pln">
</span><span class="com">// إلى العنصر الثاني في المتجه `it` يشير</span><span class="pln">

</span><span class="kwd">auto</span><span class="pln"> missing </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">find</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> </span><span class="lit">10</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> index_missing </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">distance</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> missing</span><span class="pun">);</span><span class="pln">
</span><span class="com">// تساوي 5 index_missing و  v.end() تساوي `missing` </span></pre>

<p>
	إذا كنت بحاجة إلى إجراء العديد من عمليات البحث في متجه كبير فقد يكون الأفضل أن ترتّب المتجه أولاً، ثم تستخدم خوارزمية <a data-ss1617022526="1" href="https://en.cppreference.com/w/cpp/algorithm/binary_search" rel="external nofollow">البحث الثنائي</a>.
</p>

<p>
	لإيجاد أوّل عنصر يحقّق شرطًا ما في متجه، يمكنك استخدام <code>‎std::find_if‎</code>. بالإضافة إلى المُعاملين المُمرّرين إلى الدالّة <code>‎std::find‎</code>، فإنّ الدالّة <code>‎std::find_if‎</code> تقبل معاملًا ثالثًا، وهو عبارة عن كائن دالّة (function object)، أو مؤشّر دالّة يشير إلى دالّة شرطية (predicate function). يجب أن تقبل الدالّة الشرطية عنصرًا من الحاوية كوسيط ثم تعيد قيمة قابلة للتحويل إلى قيمة بوليانية <code>‎bool‎</code> لكن دون تعديل الحاوية:
</p>

<p>
	<strong>الإصدار  ≥ C++11</strong><br><c></c>++‎&gt;
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_138" style="">
<span class="kwd">bool</span><span class="pln"> isEven</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> val</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">val </span><span class="pun">%</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> moreThan </span><span class="pun">{</span><span class="pln">
    moreThan</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> limit</span><span class="pun">):</span><span class="pln"> _limit</span><span class="pun">(</span><span class="pln">limit</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

    </span><span class="kwd">bool</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">()(</span><span class="typ">int</span><span class="pln"> val</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> val </span><span class="pun">&gt;</span><span class="pln"> _limit</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="typ">int</span><span class="pln"> _limit</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> arr</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">};</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v</span><span class="pun">(</span><span class="pln">arr</span><span class="pun">,</span><span class="pln"> arr </span><span class="pun">+</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">arr</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">arr</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]));</span><span class="pln">

std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="typ">iterator</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">find_if</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> isEven</span><span class="pun">);</span><span class="pln">
</span><span class="com">// إلى 8، أول عنصر زوجي `it`يشير</span><span class="pln">

std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="typ">iterator</span><span class="pln"> missing </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">find_if</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> moreThan</span><span class="pun">(</span><span class="lit">10</span><span class="pun">));</span><span class="pln">
</span><span class="com">//لأن كل العناصر أصغر من 10 v.end() يساوي `missing` </span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_140" style="">
<span class="com">// إيجاد أول عنصر زوجي</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">find_if</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> </span><span class="pun">[](</span><span class="typ">int</span><span class="pln"> val</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> val </span><span class="pun">%</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">});</span><span class="pln">
</span><span class="com">// إلى 8، أول عنصر زوجي `it`يشير</span><span class="pln">

</span><span class="kwd">auto</span><span class="pln"> missing </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">find_if</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> </span><span class="pun">[](</span><span class="typ">int</span><span class="pln"> val</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> val </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln">
</span><span class="pun">});</span><span class="pln">
</span><span class="com">// لأن كل العناصر أصغر من 10 v.end() يساوي `missing` </span></pre>

<h2>
	ضم المتجهات (Concatenating Vectors)
</h2>

<p>
	يمكن ضم متجه إلى آخر باستخدام التابع <code>‎insert()‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_142" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">};</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pun">};</span><span class="pln">
a</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">a</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">end</span><span class="pun">());</span></pre>

<p>
	سيفشل هذا الحلّ إذا حاولت ضمّ متجه إلى نفسه لأنّ المواصفات القياسية تنصّ على أنّ المكرّرات المُمرّرة إلى <code>‎insert()‎</code> يجب ألّا تكون من نفس نطاق عناصر الكائن المستقبِل.
</p>

<p>
	<strong>الإصدار &lt; C++‎ 11</strong>
</p>

<p>
	يمكن استخدام الدالتين <code>‎std::begin()‎</code> و <code>‎std::end()‎</code> بدلاً من استخدام توابع المتجه:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_144" style="">
<span class="pln">a</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">end</span><span class="pun">(</span><span class="pln">a</span><span class="pun">),</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">begin</span><span class="pun">(</span><span class="pln">b</span><span class="pun">),</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">end</span><span class="pun">(</span><span class="pln">b</span><span class="pun">));</span></pre>

<p>
	هذا حلّ أكثر شمولية لأنّ <code>‎b‎</code> يمكن أن تكون مصفوفة مثلًا، لكن للأسف، فهذا الحل أيضًا لا يسمح لك بضمّ متجه إلى نفسه.
</p>

<p>
	إذا لم يكن ترتيب العناصر في المتجه المستقبِل مهمًا، فإنّ معرفة عدد العناصر في كل متجه قد يجنّبك عمليات النسخ غير الضرورية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_146" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">b</span><span class="pun">.</span><span class="pln">size</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">size</span><span class="pun">())</span><span class="pln">
    a</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">a</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">end</span><span class="pun">());</span><span class="pln">
</span><span class="kwd">else</span><span class="pln">
    b</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">b</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">end</span><span class="pun">());</span></pre>

<h2>
	استخدام المتجهات كمصفوفات متعدّدة الأبعاد
</h2>

<p>
	يمكن استخدام المتّجهات كمصفوفات ثنائية الأبعاد (2D matrix) عبر تعريفها كمُتّجهة مؤلّفة من متّجهات. ويمكن تعريف مصفوفة ذات 3 صفوف و 4 أعمدة ذات قيم مساوية للصفر على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_148" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> matrix</span><span class="pun">(</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pun">(</span><span class="lit">4</span><span class="pun">));</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	صياغة التهيئة باستخدام قوائم التهيئة مشابه للمتّجهات العادية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_150" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pun">&gt;</span><span class="pln"> matrix </span><span class="pun">=</span><span class="pln">    </span><span class="pun">{</span><span class="pln">   </span><span class="pun">{</span><span class="lit">0</span><span class="pun">,</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">,</span><span class="lit">3</span><span class="pun">},</span><span class="pln">
</span><span class="pun">{</span><span class="lit">4</span><span class="pun">,</span><span class="lit">5</span><span class="pun">,</span><span class="lit">6</span><span class="pun">,</span><span class="lit">7</span><span class="pun">},</span><span class="pln">
</span><span class="pun">{</span><span class="lit">8</span><span class="pun">,</span><span class="lit">9</span><span class="pun">,</span><span class="lit">10</span><span class="pun">,</span><span class="lit">11</span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	يمكن الوصول إلى قيم هذه المتجه بنفس طريقة الوصول إلى عناصر المصفوفات ثنائية الأبعاد
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_152" style="">
<span class="typ">int</span><span class="pln"> var </span><span class="pun">=</span><span class="pln"> matrix</span><span class="pun">[</span><span class="lit">0</span><span class="pun">][</span><span class="lit">2</span><span class="pun">];</span></pre>

<p>
	التكرار على مصفوفة متعددة الأبعاد يشبة التكرارَ على المتّجهات العادية ولكن مع بعد إضافي.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_154" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> j </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> j </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">4</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">j</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> matrix</span><span class="pun">[</span><span class="pln">i</span><span class="pun">][</span><span class="pln">j</span><span class="pun">]</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_156" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> row</span><span class="pun">:</span><span class="pln"> matrix</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> col</span><span class="pun">:</span><span class="pln"> row</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> col </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تمثيل مصفوفة بمتّجه مكوّن من متّجهات يُعدُّ طريقة مناسبة لتمثيل المصفوفات متعددة الأبعاد لكنّها ليست الأفضل: إذ أنّها تُشتّت المتّجهات الفردية في الذاكرة كما أنّ هيكلة البيانات لا تساعد على التخزين المؤقت. أيضًا، يجب أن تكون أطوال صفوف المصفوفة المتعدّدة متماثلة، وهذا ليس حال متّجه المتّجهات، كما أنّ المرونة الإضافية قد تسبب الأخطاء.
</p>

<h2>
	استخدام المتجهات المرتبة لتسريع عمليات البحث
</h2>

<p>
	توفر الترويسة <algorithm> عددًا من الدوالّ المفيدة لاستخدامها على المتّجهات المُرتبة (sorted vectors)، ولا يمكن العمل مع المتّجهات المُرتّبة إلا إن كانت قيمها المرتّبة قابلة للمقارنة عبر المعامل <code>‎&lt;‎</code>.</algorithm></p>

<p>
	يمكن ترتيب متجه غير مرتب باستخدام الدالّة <code>‎std::sort()‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_158" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">;</span><span class="pln">
</span><span class="com">// بالعناصر v إضافة شيفرة لملء</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">sort</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">());</span></pre>

<p>
	تتيح المتّجهات المرتّبة بحثًا سريعًا عن العناصر باستخدام الدالّة <code>‎std::lower_bound()‎</code>، وعلى عكس <code>‎std::find()‎</code> فإن هذا التابع يجري بحثًا ثنائيا (binary search) فعّالًا على المتجه، لكن الجانب السلبي فيه أنه لا يعطي نتائج صحيحة إلّا إن كانت المتّجهات المُدخلة مُرتّبة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_160" style="">
<span class="com">// بحث عن أول عنصر يساوي 42</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pun">::</span><span class="typ">iterator</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">lower_bound</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> </span><span class="lit">42</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">it </span><span class="pun">!=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">*</span><span class="pln">it </span><span class="pun">==</span><span class="pln"> </span><span class="lit">42</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// عثرنا على العنصر</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ملاحظة: إذا لم تكن القيمة المطلوبة جزءًا من المتجه، فسيعيد <code>‎std::lower_bound()‎</code> مكرّرًا إلى أوّل عنصر يكون أكبر من القيمة المطلوبة، يسمح لنا هذا السلوك بإدراج العنصر الجديد في مكانه الصحيح في المتّجهات المُرتّبة سلفًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_162" style="">
<span class="typ">int</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> new_element </span><span class="pun">=</span><span class="pln"> </span><span class="lit">33</span><span class="pun">;</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">lower_bound</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> new_element</span><span class="pun">),</span><span class="pln"> new_element</span><span class="pun">);</span></pre>

<p>
	إذا أردت إدراج الكثير من العناصر دفعة واحدة، فقد يكون الأفضل استدعاء <code>‎push_back()‎</code> عليهم جميعًا، ثم استدعاء <code>‎std::sort()‎</code> بعد إدراج جميع العناصر. في هذه الحالة، يمكن أن تعادل التكلفة المتزايدة لترتيب المتجه التكلفةَ المخُفّضة لإدراج عناصر جديدة في نهاية المتجه بدلًا من البحث عن موضعه المناسب.
</p>

<p>
	إذا كان المتجه يحتوي على عدّة عناصر بنفس القيمة، فسيعيد <code>‎std::lower_bound()‎</code> مُكرِّرًا إلى العنصر الأول من القيمة التي يُبحث عنها. لكن إن أردت إدراج عنصر جديد بعد العنصر الأخير من القيمة التي تبحث عنها، فيجب استخدام الدالّة <code>‎std::upper_bound()‎</code> لأنّها تقلّل من تحويل العناصر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_164" style="">
<span class="pln">v</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">upper_bound</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> new_element</span><span class="pun">),</span><span class="pln"> new_element</span><span class="pun">);</span></pre>

<p>
	إذا أردت الحصول على مكرّر الحدّ الأعلى (upper bound iterators) ومكرّر الحدّ الأدنى (lower bound iterators)، فيمكنك استخدام الدالة <code>‎std::equal_range()‎</code> للحصول عليهما معًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_166" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">pair</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pun">::</span><span class="typ">iterator</span><span class="pun">,</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pun">::</span><span class="typ">iterator</span><span class="pun">&gt;</span><span class="pln"> rg </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">equal_range</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> </span><span class="lit">42</span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pun">::</span><span class="typ">iterator</span><span class="pln"> lower_bound </span><span class="pun">=</span><span class="pln"> rg</span><span class="pun">.</span><span class="pln">first</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pun">::</span><span class="typ">iterator</span><span class="pln"> upper_bound </span><span class="pun">=</span><span class="pln"> rg</span><span class="pun">.</span><span class="pln">second</span><span class="pun">;</span></pre>

<p>
	للتحقّق من وجود عنصر ما في متّجه مُرتّب، يمكنك استخدام الدالّة <code>‎std::binary_search()‎</code> مع أنها غير مقصورة على المتّجهات:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_168" style="">
<span class="kwd">bool</span><span class="pln"> exists </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">binary_search</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> value_to_find</span><span class="pun">);</span></pre>

<h2>
	تقليص سعة متجه
</h2>

<p>
	تزيد المتّجهات في سعتها تلقائيًا عند إدراج عناصر جديدة إن كانت هناك حاجة لذلك، لكنها لا تقلّص سعتها بعد إزالة عنصر ما.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_170" style="">
<span class="com">// تهيئة متّجه مئوي</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v</span><span class="pun">(</span><span class="lit">100</span><span class="pun">);</span><span class="pln">

</span><span class="com">// سعة المتّجه دائما ما تكون أكبر من حجمه</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> old_capacity </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">capacity</span><span class="pun">();</span><span class="pln">
</span><span class="com">// old_capacity &gt;= 100</span><span class="pln">

</span><span class="com">// إزالة نصف العناصر</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">erase</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">50</span><span class="pun">,</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">());</span><span class="pln">    </span><span class="com">// تخفيض الحجم من 50 إلى 100</span><span class="pln">
</span><span class="com">// (v.capacity() == old_capacity)</span></pre>

<p>
	يمكننا نسخ محتويات المتجه إلى متجه مؤقت جديد إن أردنا تقليل سعته، وسيكون للمتجه الجديد الحد الأدنى من السعة اللازمة لتخزين جميع عناصر المتجه الأصلية والتي يمكن أن تكون أقل بكثير من سعة المتجه الأولى في حال تقليص الحجم الأصلي بشكل كبير. يمكننا بعد ذلك تبديل المتجه الأصلي بالمتجه المؤقت المُقلّص:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_172" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pun">(</span><span class="pln">v</span><span class="pun">).</span><span class="pln">swap</span><span class="pun">(</span><span class="pln">v</span><span class="pun">);</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	في C++‎ 11، يمكننا استخدام التابع <code>‎shrink_to_fit()‎</code> لتحقيق التأثير نفسه:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_174" style="">
<span class="pln">v</span><span class="pun">.</span><span class="pln">shrink_to_fit</span><span class="pun">();</span></pre>

<p>
	ملاحظة: التابع <code>‎shrink_to_fit()‎</code> هو مجرد طلب، ولا يضمن تقليص السعة.
</p>

<h2>
	حجم المتجهات وسعتها
</h2>

<p>
	حجم المتّجه هو عدد عناصره:
</p>

<ol>
<li>
		يمكنك الحصول على الحجم الحالي للمتّجه بواسطة الدالة التابعة <code>‎size()‎</code>، وتعيد الدالّة <code>‎empty()‎</code> القيمة <code>‎true‎</code> إن كان الحجم يساوي 0:
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_176" style="">
<span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">};</span><span class="pln"> </span><span class="com">// 3 الحجم يساوي</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pun">::</span><span class="pln">size_type size </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">size</span><span class="pun">();</span><span class="pln">
cout </span><span class="pun">&lt;&lt;</span><span class="pln"> size </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 3</span><span class="pln">
cout </span><span class="pun">&lt;&lt;</span><span class="pln"> boolalpha </span><span class="pun">&lt;&lt;</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">empty</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// false</span></pre>

<ol start="2">
<li>
		تبدأ المتّجهات المُنشأة افتراضيا بالحجم 0:
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_178" style="">
<span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 0 الحجم يساوي</span><span class="pln">
cout </span><span class="pun">&lt;&lt;</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">size</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 0</span></pre>

<ol start="3">
<li>
		تؤدّي إضافة <code>‎N‎</code> عنصر إلى المتجه (مثلا، عبر الدوالّ <code>‎push_back()‎</code> أو <code>‎insert()‎</code> أو <code>‎resize()‎</code>) إلى زيادة الحجم بالقيمة <code>‎N‎</code>.
	</li>
	<li>
		تؤدّي إزالة <code>‎N‎</code> عنصر من المتجه (على سبيل المثال عند استخدام الدوالّ <code>‎pop_back()‎</code> أو <code>‎erase()‎</code> أو <code>‎clear()‎</code>) إلى تقليص الحجم بالقيمة <code>‎N‎</code>.
	</li>
	<li>
		الحد الأقصى لحجم المتجه يتعلق بالتنفيذ (implementation-specific)، ولكن لا تشغل نفسك بهذا، فعلى الأرجح ستُستنزف ذاكرة الوصول العشوائي (RAM) قبل بلوغ الحد الأقصى:
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_180" style="">
<span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">size_type max_size </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">max_size</span><span class="pun">();</span><span class="pln">
cout </span><span class="pun">&lt;&lt;</span><span class="pln"> max_size </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">resize</span><span class="pun">(</span><span class="pln">max_size</span><span class="pun">);</span><span class="pln"> </span><span class="com">// لن تعمل على الأرجح</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="lit">1</span><span class="pun">);</span><span class="pln"> </span><span class="com">// بالتأكيد لن تعمل</span></pre>

<p>
	خطأ شائع: حجم المتجه لا يكون بالضرورة (أو حتى عادة) من النوع <code>‎int‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_182" style="">
<span class="com">// شيفرة سيئة</span><span class="pln">
</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v_bad</span><span class="pun">(</span><span class="pln">N</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln"> </span><span class="com">// N إنشاء متجه كبير حجمه</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> v_bad</span><span class="pun">.</span><span class="pln">size</span><span class="pun">();</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// int ليس بالضرورة أن يكون الحجم من النوع</span><span class="pln">
    do_something</span><span class="pun">(</span><span class="pln">v_bad</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تختلف سعة المتجه عن حجمه، ففي حين أنّ الحجم يمثّل ببساطة عدد العناصر التي يحتويها المتجه حاليًا، إلا أنّ السعة تمثّل عدد العناصر التي حُجِزت ذاكرة لها، وهذا مفيد لأنّ (إعادة) تخصيص أحجام كبيرة في الذاكرة يمكن أن يكون مكلّفا للغاية.
</p>

<ol>
<li>
		يمكن الحصول على السعة الحالية للمتّجه عبر التابع <code>‎capacity()‎</code>. وتذكّر أنّ السعة دائمًا أكبر من أو تساوي الحجم:
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_184" style="">
<span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">};</span><span class="pln"> </span><span class="com">// الحجم يساوي 3 لكنّ السعة يمكن أن تكون أكبر</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pun">::</span><span class="pln">size_type capacity </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">capacity</span><span class="pun">();</span><span class="pln">
cout </span><span class="pun">&lt;&lt;</span><span class="pln"> capacity </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln"> </span></pre>

<ol start="2">
<li>
		يمكنك حجز السعة يدويًا عبر دالّة <code>‎reserve( N )‎</code> (تغيّر سعة المتجه إلى <code>‎N‎</code>):
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_186" style="">
<span class="com">// شيفرة سيئة</span><span class="pln">
</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v_bad</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10000</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    v_bad</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">i</span><span class="pun">);</span><span class="pln"> </span><span class="com">// الكثير من تخصيصات الذاكرة </span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">//  شيفرة جيدة</span><span class="pln">
</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v_good</span><span class="pun">;</span><span class="pln">
v_good</span><span class="pun">.</span><span class="pln">reserve</span><span class="pun">(</span><span class="lit">10000</span><span class="pun">);</span><span class="pln"> </span><span class="com">// هذا جيد، لأنه ستكون هناك عملية تخصيص واحدة فقط</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10000</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    v_good</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">i</span><span class="pun">);</span><span class="pln"> </span><span class="com">// لا حاجة لتخصيص الذاكرة</span><span class="pln">
</span><span class="pun">}</span></pre>

<ol start="3">
<li>
		يمكنك أن تطلب تحرير السعة الزائدة عبر <code>‎shrink_to_fit()‎</code> (لكنّ ذلك غير مضمون). هذا مفيد لتوفير الذاكرة المستخدمة:
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_188" style="">
<span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> </span><span class="pun">};</span><span class="pln"> </span><span class="com">// الحجم يساوي 5، ونفترض أنّ السعة تساوي 6</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">shrink_to_fit</span><span class="pun">();</span><span class="pln"> </span><span class="com">// السعة من الممكن أنها تساوي الآن 5، لكن يمكن أن تساوي 6</span><span class="pln">
cout </span><span class="pun">&lt;&lt;</span><span class="pln"> boolalpha </span><span class="pun">&lt;&lt;</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">capacity</span><span class="pun">()</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">size</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln"> </span></pre>

<p>
	يدير المتّجهُ السّعةَ جزئيًّا، فقد تقرّر زيادة سعته عند إضافة عناصر إليه. يفضل الكثير من المنفِّذين (Implementers) استخدام 2 أو 1.5 كعامل توسيع. وعلى الناحية الأخرى، لا تتقلّص سعة المتّجهات تلقائيًّا في العادة. مثلا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_190" style="">
<span class="com">// السعة يمكن أن تساوي 0، لكن ليس بالضرورة</span><span class="pln">
</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v</span><span class="pun">;</span><span class="pln"> 

</span><span class="com">// السعة تساوي 1 على الأرجح الآن</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="lit">1</span><span class="pun">);</span><span class="pln"> 

</span><span class="com">// الحجم صار 0 لكن السعة ما تزال تساوي 1</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">clear</span><span class="pun">();</span><span class="pln"> 

</span><span class="com">// لنفترض أن الحجم والسعة يساويان 4</span><span class="pln">
v </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pln"> </span><span class="pun">};</span><span class="pln">  

</span><span class="com">// ازدياد السعة، لنفترض أنها أصبحت تساوي 6، أي بمعدل توسع 1.5</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="lit">5</span><span class="pun">);</span><span class="pln"> 

</span><span class="com">// لا تغيير في السعة</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="lit">6</span><span class="pun">);</span><span class="pln"> 

</span><span class="com">// ازدياد السعة، لنفترض أنها أصبحت تساوي 9، أي بمعدل توسّع 1.5</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="lit">7</span><span class="pun">);</span><span class="pln"> 

</span><span class="com">// السّعة لم تتغير</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">pop_back</span><span class="pun">();</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">pop_back</span><span class="pun">();</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">pop_back</span><span class="pun">();</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">pop_back</span><span class="pun">();</span><span class="pln"> </span></pre>

<h2>
	إبطال المكررات والمؤشرات (Iterator/Pointer Invalidation)
</h2>

<p>
	لا يمكن أن تَبطُل المُكرّرات والمؤشّرات التي تشير إلى متجه ما إلا عند إجراء عمليات معينة، إذ سيؤدّي استخدام مكرّرات أو مؤشّرات غير صالحة إلى سلوك غير محدّد. إليك بعض العمليات التي تُبطل المكرّرات والمؤشّرات:
</p>

<ul>
<li>
		أيّ عملية إدخال تغيّر سعة المتجه ستُبطل جميع المُكرّرات والمؤشّرات التي تشير إلى ذلك المتجه:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_192" style="">
<span class="com">// حجم المتجه يساوي 5 وسعتها غير معروفة</span><span class="pln">
</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v</span><span class="pun">(</span><span class="lit">5</span><span class="pun">);</span><span class="pln"> 
</span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p1 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">v</span><span class="pun">[</span><span class="lit">0</span><span class="pun">];</span><span class="pln">

</span><span class="com">// بما أن السعة مجهولة p1 ربما أُبطِل</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="lit">2</span><span class="pun">);</span><span class="pln"> 

</span><span class="com">// السعة تساوي 20 على الأقل الآن</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">reserve</span><span class="pun">(</span><span class="lit">20</span><span class="pun">);</span><span class="pln"> 
</span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p2 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">v</span><span class="pun">[</span><span class="lit">0</span><span class="pun">];</span><span class="pln">

</span><span class="com">// يساوي 7 الآن v لأن حجم p2 لم يتم إبطال</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="lit">4</span><span class="pun">);</span><span class="pln"> 

</span><span class="com">// إدارج 30 عنصرا في النهاية، سيتجاوز الحجم السعة السابقة، لذا</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> </span><span class="lit">30</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pun">);</span><span class="pln">    
</span><span class="com">// صار باطلا الآن `p2` فعلى الأرجح أن</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p3 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">v</span><span class="pun">[</span><span class="lit">0</span><span class="pun">];</span><span class="pln">

</span><span class="com">// باطلا `p3`تجاوز السعة، وسيصبح</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">reserve</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">capacity</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">20</span><span class="pun">);</span><span class="pln"> </span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_194" style="">
<span class="kwd">auto</span><span class="pln"> old_cap </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">capacity</span><span class="pun">();</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">shrink_to_fit</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">if</span><span class="pun">(</span><span class="pln">old_cap </span><span class="pun">!=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">capacity</span><span class="pun">())</span><span class="pln">
</span><span class="com">// إبطال المكررات</span></pre>

<ul>
<li>
		أيّ عملية إدراج لا تزيد في السعة، ستُبطل المكررات والمؤشّرات التي تشير إلى العناصر الموجودة في الموضع الذي حدث الإدراج عنده أو بعده. يتضمّن ذلك المُكرر <code>‎end‎</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_196" style="">
<span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v</span><span class="pun">(</span><span class="lit">5</span><span class="pun">);</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">reserve</span><span class="pun">(</span><span class="lit">20</span><span class="pun">);</span><span class="pln"> </span><span class="com">// السعة تساوي 20 على الأقل</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p1 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">v</span><span class="pun">[</span><span class="lit">0</span><span class="pun">];</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p2 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">v</span><span class="pun">[</span><span class="lit">3</span><span class="pun">];</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln"> </span><span class="com">// أصبح باطلا، ولكن بما أنّ السعة لم تتغير  `p2` </span><span class="pln">
                                           </span><span class="com">// يبقى صالحا `p1` فإن</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p3 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">v</span><span class="pun">[</span><span class="pln">v</span><span class="pun">.</span><span class="pln">size</span><span class="pun">()</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pun">];</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln"> </span><span class="com">// ما زالا صالحين `p3` و`p1` السعة لم تتغير لذا فإنّ</span></pre>

<ul>
<li>
		ستؤدّي أيّ عملية إزالة إلى إبطال المكرّرات أو المؤشّرات التي تشير إلى العناصر التي أزيلت أو التي بعدها. يتضمن ذلك المكرّر <code>‎end‎</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_198" style="">
<span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p1 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">v</span><span class="pun">[</span><span class="lit">0</span><span class="pun">];</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p2 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">v</span><span class="pun">[</span><span class="lit">5</span><span class="pun">];</span><span class="pln">
v</span><span class="pun">.</span><span class="pln">erase</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">());</span><span class="pln"> </span><span class="com">// `p2` ما زال صالحا على عكس `p1`</span></pre>

<ul>
<li>
		المعامل <code>‎operator=‎</code> و التابع <code>‎clear()‎</code> سيبطلان كل المكرّرات أو المؤشّرات التي تشير إلى المتجه.
	</li>
</ul>
<h2>
	إيجاد العنصر الأكبر/الأصغر مع فهرسه في متجه
</h2>

<p>
	لإيجاد أكبر أو أصغر عنصر مخزّن في متجه، يمكنك استخدام التابعين <code>‎std::max_element‎</code> و <code>std::max_element</code> على الترتيب، هذان التابعان مُعرّفان في الترويسة <a data-ss1617022526="1" href="https://en.cppreference.com/w/cpp/algorithm" rel="external nofollow"><algorithm></algorithm></a>. إذا كانت هناك عدّة عناصر تساوي القيمة الأكبر (أو الأصغر) في متجه، فإن التوابع ستعيد المُكرّر الذي يشير إلى أوّل تلك العناصر. بالنسبة للمتّجهات الفارغة، تُعاد <code>v.end()‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_200" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> maxElementIndex </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">max_element</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">())</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">();</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> maxElement </span><span class="pun">=</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">max_element</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">());</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> minElementIndex </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">min_element</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">())</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">();</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> minElement </span><span class="pun">=</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">min_element</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">());</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"maxElementIndex:"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> maxElementIndex </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", maxElement:"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> maxElement </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"minElementIndex:"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> minElementIndex </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", minElement:"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> minElement </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span></pre>

<p>
	المخرجات:
</p>

<pre class="ipsCode" id="ips_uid_8850_204">
maxElementIndex:3, maxElement:10
minElementIndex:1, minElement:2
</pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	يمكن الحصول على الحدّ الأصغر والحد الأكبر في متجه معًا، باستخدام التابع <code>std::minmax_element</code>، وهو مُعرّف في الترويسة <a data-ss1617022526="1" href="https://en.cppreference.com/w/cpp/algorithm" rel="external nofollow"><algorithm></algorithm></a>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_206" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> minmax </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">minmax_element</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">());</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"minimum element: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln">minmax</span><span class="pun">.</span><span class="pln">first </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"maximum element: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln">minmax</span><span class="pun">.</span><span class="pln">second </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span></pre>

<p>
	المخرجات:
</p>

<pre class="ipsCode" id="ips_uid_8850_208">
minimum element: 2
maximum element: 10
</pre>

<h2>
	تحويل مصفوفة إلى متجه
</h2>

<p>
	يمكن تحويل مصفوفة بسهولة إلى متجه باستخدام <code>‎std::begin‎</code> و <code>‎std::end‎</code>:
</p>

<p>
	<strong>الإصدار≥ C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_210" style="">
<span class="typ">int</span><span class="pln"> values</span><span class="pun">[</span><span class="lit">5</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> </span><span class="pun">};</span><span class="pln">    </span><span class="com">// المصفوفة المصدرية</span><span class="pln">

std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">begin</span><span class="pun">(</span><span class="pln">values</span><span class="pun">),</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">end</span><span class="pun">(</span><span class="pln">values</span><span class="pun">));</span><span class="pln"> </span><span class="com">// نسخ المصفوفة إلى متجه جديد</span><span class="pln">

</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">x</span><span class="pun">:</span><span class="pln"> v</span><span class="pun">)</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> x </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" "</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></pre>

<p>
	المخرجات:
</p>

<pre class="ipsCode" id="ips_uid_8850_212">
1 2 3 4 5 
</pre>

<p>
	تحويل وسائط <code>main</code> إلى متجه من السلاسل النصية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_214" style="">
<span class="typ">int</span><span class="pln"> main</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> argc</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> argv</span><span class="pun">[])</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&gt;</span><span class="pln">  args</span><span class="pun">(</span><span class="pln">argv</span><span class="pun">,</span><span class="pln"> argv </span><span class="pun">+</span><span class="pln"> argc</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكن أيضًا استخدام قائمة تهيئة <code>&lt;&gt;initializer_list</code> (الإصدار C++11) لتهيئة المتجه على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_216" style="">
<span class="pln">initializer_list</span><span class="str">&lt;int&gt;</span><span class="pln"> arr </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">,</span><span class="lit">3</span><span class="pun">,</span><span class="lit">4</span><span class="pun">,</span><span class="lit">5</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> vec1 </span><span class="pun">{</span><span class="pln">
    arr
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> i</span><span class="pun">:</span><span class="pln"> vec1</span><span class="pun">)</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> i </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span></pre>

<h2>
	الدوال التي تعيد متجهات كبيرة
</h2>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	في الإصدار C++‎ 11، يُطلب من المُصرّفات النقل ضمنيًّا من المتغير المحلي المٌعاد. وكذلك يمكن لمعظم المُصرّفات إهمال النسخ (copy elision) في كثير من الحالات، وإسقاط النقل تمامًا. ونتيجةً لذلك فإنّ إعادة الكائنات الكبيرة التي يمكن نقلها بدون كلفة كبيرة لا تتطّلب معالجة خاصة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_218" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;vector&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="com">// (NRVO) “إن عجز المصرف عن إنجاز “ترشيد القيمة المعادة المسماة</span><span class="pln">
</span><span class="com">// إلى القيمة المعادة v وتجنّب النقل بشكل كامل، فعليه أن ينقل من</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> fillVector</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v</span><span class="pun">;</span><span class="pln">
    v</span><span class="pun">.</span><span class="pln">reserve</span><span class="pun">(</span><span class="pln">b </span><span class="pun">-</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> a</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;=</span><span class="pln"> b</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        v</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">i</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> v</span><span class="pun">;</span><span class="pln"> </span><span class="com">// نقل ضمني</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// إعلان المتجه وملؤه</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> vec </span><span class="pun">=</span><span class="pln"> fillVector</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// طباعة المتجه</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> value</span><span class="pun">:</span><span class="pln"> vec</span><span class="pun">)</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" "</span><span class="pun">;</span><span class="pln"> </span><span class="com">// "1 2 3 4 5 6 7 8 9 10 "</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>الإصدار &lt; C++11</strong><br><c></c>++‎&gt;
</p>

<p>
	قبل الإصدار C++‎ 11، كان يُسمَح بإهمال النسخ (copy elision)، وقد طُبِّق ذلك في معظم المُصرّفات. ومع ذلك، ونظرًا لغياب دلالات النقل (move semantics)، فقد ترى في الشيفرات القديمة أو الشيفرات التي يجب تصريفها بمصرّفات قديمة لا تدعم هذه الميزة أنّ المتّجهات تُمرَّر كوسائط إخراج (output arguments) لمنع النسخ غير الضروري:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8850_220" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;vector&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="com">// تمرير المتجه بالمرجع</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> fillVectorFrom_By_Ref</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> v</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    assert</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">empty</span><span class="pun">());</span><span class="pln">
    v</span><span class="pun">.</span><span class="pln">reserve</span><span class="pun">(</span><span class="pln">b </span><span class="pun">-</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> a</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;=</span><span class="pln"> b</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        v</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">i</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// التصريح عن متجه</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> vec</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// ملء المتجه</span><span class="pln">
    fillVectorFrom_By_Ref</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">,</span><span class="pln"> vec</span><span class="pun">);</span><span class="pln">
    </span><span class="com">// طباعة المتجه</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="typ">const_iterator</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> vec</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">();</span><span class="pln"> it </span><span class="pun">!=</span><span class="pln"> vec</span><span class="pun">.</span><span class="pln">end</span><span class="pun">();</span><span class="pln"> </span><span class="pun">++</span><span class="pln">it</span><span class="pun">)</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> it </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" "</span><span class="pun">;</span><span class="pln"> </span><span class="com">// "1 2 3 4 5 6 7 8 9 10 "</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هذ الدرس جزء من <a data-ss1617022526="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة مقالات عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرف- للفصل Chapter 49: std::vector من كتاب <a data-ss1617022526="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">941</guid><pubDate>Tue, 28 Jul 2020 13:09:00 +0000</pubDate></item></channel></rss>
