<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-32334553</id><updated>2011-12-15T06:50:24.178+04:00</updated><title type='text'>C++ in depth</title><subtitle type='html'>Простой блог о непростом языке</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://zubankov.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32334553/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://zubankov.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Григорий Зубанков</name><uri>http://www.blogger.com/profile/11175792768984667084</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://sura.ru/ss/greg/IMG_1790_mod.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>11</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-32334553.post-7417189074345697173</id><published>2007-02-16T13:34:00.000+03:00</published><updated>2007-02-16T14:12:42.440+03:00</updated><title type='text'>Головоловка</title><content type='html'>Синтаксис языка С++ иногда просто поражает.  &lt;br/&gt;Как Вы думаете что означает это объявление:&lt;br/&gt;&lt;pre&gt;&lt;span&gt;&lt;br/&gt;&lt;span&gt;char&lt;/span&gt; &lt;span&gt;(*(*(*C::foo(&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;(C::*)(&lt;/span&gt;&lt;span&gt;int&lt;/span&gt; &lt;span&gt;const&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;const&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;const&lt;/span&gt;&lt;span&gt;))())[][1];&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/32334553-7417189074345697173?l=zubankov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zubankov.blogspot.com/feeds/7417189074345697173/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=32334553&amp;postID=7417189074345697173' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32334553/posts/default/7417189074345697173'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32334553/posts/default/7417189074345697173'/><link rel='alternate' type='text/html' href='http://zubankov.blogspot.com/2007/02/blog-post.html' title='Головоловка'/><author><name>Григорий Зубанков</name><uri>http://www.blogger.com/profile/11175792768984667084</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://sura.ru/ss/greg/IMG_1790_mod.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32334553.post-116299112143119589</id><published>2006-11-08T16:02:00.000+03:00</published><updated>2006-11-08T16:05:21.910+03:00</updated><title type='text'>Comeau всегда прав!...?</title><content type='html'>Код, который я пишу на работе, должен собираться сразу несколькими компиляторами. Само собой иногда возникают разногласия в их трактовках стандарта языка. Обычно, при неоднозначном результате, я считаю правым gcc, однако, в особо щекотливых ситуациях, проверяю код on-line вариантом &lt;a href="http://www.comeaucomputing.com/tryitout/"&gt;Comeau&lt;/a&gt;. Лишь затем «курю» стандарт, уточняя оставшиеся непонятными моменты. Comeau всегда дает мне 90% понимания сутации.&lt;br /&gt;&lt;a href="http://sura.ru/ss/greg/articles/Comeau%20всегда%20прав.html"&gt;[Дальше...]&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/32334553-116299112143119589?l=zubankov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zubankov.blogspot.com/feeds/116299112143119589/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=32334553&amp;postID=116299112143119589' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32334553/posts/default/116299112143119589'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32334553/posts/default/116299112143119589'/><link rel='alternate' type='text/html' href='http://zubankov.blogspot.com/2006/11/comeau.html' title='Comeau всегда прав!...?'/><author><name>Григорий Зубанков</name><uri>http://www.blogger.com/profile/11175792768984667084</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://sura.ru/ss/greg/IMG_1790_mod.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32334553.post-116107108847270788</id><published>2006-10-17T11:29:00.000+04:00</published><updated>2006-10-17T11:46:00.800+04:00</updated><title type='text'>Баг VS или как получить доступ к приватному интерфейсу</title><content type='html'>Случайно столкнулся c интересным багом в VS2003/VS2005.&lt;br /&gt;Нехитрый прием позволяет получить доступ к приватному интерфейсу наследуемого класса.&lt;br /&gt;&lt;tr&gt;&lt;td&gt;&lt;pre&gt;&lt;font color="white" face="CourierNew" size=3&gt;&lt;br&gt;&lt;font color="#0000ff" &gt;struct&lt;/font&gt; &lt;font color="#000000" &gt;ifoo&lt;/font&gt;&lt;br&gt;&lt;font color="#000000" &gt;{&lt;/font&gt;&lt;br&gt;  &lt;font color="#0000ff" &gt;void&lt;/font&gt; &lt;font color="#000000" &gt;test()&lt;/font&gt; &lt;font color="#000000" &gt;{}&lt;/font&gt;&lt;br&gt;&lt;font color="#000000" &gt;};&lt;/font&gt;&lt;br&gt;&lt;br&gt;&lt;font color="#0000ff" &gt;class&lt;/font&gt; &lt;font color="#000000" &gt;foo&lt;/font&gt; &lt;font color="#000000" &gt;:&lt;/font&gt; &lt;font color="#0000ff" &gt;private&lt;/font&gt; &lt;font color="#000000" &gt;ifoo&lt;/font&gt;&lt;br&gt;&lt;font color="#000000" &gt;{&lt;/font&gt;&lt;br&gt;&lt;font color="#000000" &gt;};&lt;/font&gt;&lt;br&gt;&lt;br&gt;&lt;font color="#0000ff" &gt;struct&lt;/font&gt; &lt;font color="#0000ff" &gt;delegate&lt;/font&gt;&lt;br&gt;&lt;font color="#000000" &gt;{&lt;/font&gt;&lt;br&gt;  &lt;font color="#0000ff" &gt;delegate&lt;/font&gt;&lt;font color="#000000" &gt;(ifoo*&lt;/font&gt; &lt;font color="#000000" &gt;i)&lt;/font&gt; &lt;font color="#000000" &gt;{&lt;/font&gt; &lt;font color="#000000" &gt;i-&amp;gt;test();&lt;/font&gt; &lt;font color="#000000" &gt;}&lt;/font&gt;&lt;br&gt;&lt;font color="#000000" &gt;};&lt;/font&gt;&lt;br&gt;&lt;br&gt;&lt;font color="#0000ff" &gt;class&lt;/font&gt; &lt;font color="#000000" &gt;bar&lt;/font&gt; &lt;font color="#000000" &gt;:&lt;/font&gt; &lt;font color="#0000ff" &gt;private&lt;/font&gt; &lt;font color="#000000" &gt;foo&lt;/font&gt;&lt;br&gt;&lt;font color="#000000" &gt;{&lt;/font&gt;&lt;br&gt;&lt;font color="#0000ff" &gt;public&lt;/font&gt;&lt;font color="#000000" &gt;:&lt;/font&gt;&lt;br&gt;  &lt;font color="#000000" &gt;bar()&lt;/font&gt; &lt;font color="#000000" &gt;{&lt;/font&gt; &lt;font color="#0000ff" &gt;delegate&lt;/font&gt;&lt;font color="#000000" &gt;(&lt;/font&gt;&lt;font color="#0000ff" &gt;this&lt;/font&gt;&lt;font color="#000000" &gt;);&lt;/font&gt; &lt;font color="#000000" &gt;}&lt;/font&gt; &lt;font color="#008000" &gt;// sic! &amp;#1074;&amp;#1099;&amp;#1079;&amp;#1086;&amp;#1074; ifoo::test&lt;/font&gt;&lt;br&gt;&lt;font color="#000000" &gt;};&lt;/font&gt;&lt;/font&gt;&lt;/pre&gt;&lt;/td&gt;&lt;br /&gt;Эмпирические исследования показали, что прием работает только если &lt;b&gt;ifoo&lt;/b&gt; является структурой и &lt;b&gt;delegate&lt;/b&gt; используется как временный объект.&lt;br /&gt;&lt;br /&gt;Не устаю предупреждать:&lt;br /&gt;&lt;i&gt;Beware of bugs&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/32334553-116107108847270788?l=zubankov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zubankov.blogspot.com/feeds/116107108847270788/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=32334553&amp;postID=116107108847270788' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32334553/posts/default/116107108847270788'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32334553/posts/default/116107108847270788'/><link rel='alternate' type='text/html' href='http://zubankov.blogspot.com/2006/10/vs.html' title='Баг VS или как получить доступ к приватному интерфейсу'/><author><name>Григорий Зубанков</name><uri>http://www.blogger.com/profile/11175792768984667084</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://sura.ru/ss/greg/IMG_1790_mod.jpg'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32334553.post-115657292366223348</id><published>2006-08-26T10:10:00.000+04:00</published><updated>2006-08-26T10:15:23.766+04:00</updated><title type='text'>Отпуск</title><content type='html'>Впереди долгожданный отпуск! Улетаю на две недели к черному морю.&lt;br /&gt;Обещаю по возвращению порадовать читателей новыми интересными постами.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/32334553-115657292366223348?l=zubankov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zubankov.blogspot.com/feeds/115657292366223348/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=32334553&amp;postID=115657292366223348' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32334553/posts/default/115657292366223348'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32334553/posts/default/115657292366223348'/><link rel='alternate' type='text/html' href='http://zubankov.blogspot.com/2006/08/blog-post_26.html' title='Отпуск'/><author><name>Григорий Зубанков</name><uri>http://www.blogger.com/profile/11175792768984667084</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://sura.ru/ss/greg/IMG_1790_mod.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32334553.post-115657213071642741</id><published>2006-08-26T09:46:00.000+04:00</published><updated>2006-08-26T10:07:09.636+04:00</updated><title type='text'>ADL в деле</title><content type='html'>Продолжение предыдущего поста "Особенности поиска имен".&lt;br /&gt;&lt;br /&gt;Как заставить компилятор при поиске &lt;b&gt;operator&lt;&lt;&lt;/b&gt; заглянуть в наше собственное пространство имен?&lt;br /&gt;В предыдущем посте я упомянул про &lt;b&gt;ADL&lt;/b&gt; и его особенности:&lt;br /&gt;"...&lt;b&gt;ADL&lt;/b&gt; предполагает поиск имен в пространствах имен типов агрументов анализируемого выражения..."&lt;br /&gt;&lt;br /&gt;Этот вариант поиска имен нам и поможет.&lt;br /&gt;Вызов &lt;b&gt;operator&lt;&lt;&lt;/b&gt; находится в &lt;b&gt;operator=&lt;/b&gt; класса &lt;b&gt;std::ostream_iterator&lt;/b&gt;, а типами аргументов этого выражения являются &lt;b&gt;std::ostream&lt;/b&gt; и тип передаваемый &lt;b&gt;std::ostream_iterator&lt;/b&gt; в качестве первого параметра шаблона. Мы сами явно его задаем, создавая конкретный экземпляр класса:&lt;br /&gt;&lt;tr&gt;&lt;td&gt;&lt;pre&gt;&lt;font color="white" face="CourierNew" size=3&gt;&lt;br&gt;&lt;font color="#000000" &gt;std::ostream_iterator&amp;lt;&lt;/font&gt; &lt;font color="#000000" &gt;&lt;b&gt;std::pair&amp;lt;std::string,&lt;/b&gt;&lt;/font&gt; &lt;font color="#0000ff" &gt;&lt;b&gt;int&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000" &gt;&lt;b&gt;&amp;gt;&lt;/b&gt;&lt;/font&gt; &lt;font color="#000000" &gt;&amp;gt;(std::cout)&lt;/font&gt;&lt;/font&gt;&lt;/pre&gt;&lt;/td&gt;&lt;br /&gt;Заменив &lt;b&gt;std::pair&amp;lt;std::string, int&amp;gt;&lt;/b&gt; на некоторый тип (назовен его &lt;b&gt;wrapper&lt;/b&gt;) из того же пространства имен что и &lt;b&gt;operator&lt;&lt;&lt;/b&gt;, мы заставим компилятор произвести поиск в этом пространстве имен. Следовательно, наш вариант &lt;b&gt;operator&lt;&lt;&lt;/b&gt; будет найдет.&lt;br /&gt;&lt;br /&gt;Отлично. Проблема поиска решена. Но появились две другие, к счастью легко решаемые проблемы.&lt;br /&gt;Первая заключается в том, что в определении &lt;b&gt;operator=&lt;/b&gt; класса &lt;b&gt;std::ostream_iterator&lt;/b&gt; требуется теперь в качестве аргумента объект типа &lt;b&gt;wrapper const&amp;&lt;/b&gt;, а передается ему &lt;b&gt;std::pair&amp;lt;const std::string, int&amp;gt;&lt;/b&gt;.&lt;br /&gt;Вторая проблема обратна первой. Наш &lt;b&gt;operator&lt;&lt;&lt;/b&gt; требует в качестве второго аргумента &lt;b&gt;std::pair&amp;lt;const std::string, int&amp;gt; const&amp;&lt;/b&gt;, а передается ему &lt;b&gt;wrapper&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;Итого, объект типа &lt;b&gt;wrapper&lt;/b&gt; должен уметь неявно конструироваться из &lt;b&gt;std::pair&amp;lt;const std::string, int&amp;gt;&lt;/b&gt; (проблема 1), неявно преобразовываться к ссылке на константу этого типа (проблема 2), а также хранить саму ссылку.&lt;br /&gt;Обобщая, сам тип можно сделать шаблонным:&lt;br /&gt;&lt;tr&gt;&lt;td&gt;&lt;pre&gt;&lt;font color="white" face="CourierNew" size=3&gt;&lt;br&gt;&lt;font color="#0000ff" &gt;template&lt;/font&gt; &lt;font color="#000000" &gt;&amp;lt;&lt;/font&gt;&lt;font color="#0000ff" &gt;class&lt;/font&gt; &lt;font color="#000000" &gt;T&amp;gt;&lt;/font&gt;&lt;br&gt;&lt;font color="#0000ff" &gt;class&lt;/font&gt; &lt;font color="#000000" &gt;wrapper&lt;/font&gt;&lt;br&gt;&lt;font color="#000000" &gt;{&lt;/font&gt;&lt;br&gt;  &lt;font color="#000000" &gt;T&amp;amp;&lt;/font&gt; &lt;font color="#000000" &gt;t_;&lt;/font&gt;  &lt;font color="#008000" &gt;// &amp;#1093;&amp;#1088;&amp;#1072;&amp;#1085;&amp;#1080;&amp;#1084;&amp;#1072;&amp;#1103; &amp;#1089;&amp;#1089;&amp;#1099;&amp;#1083;&amp;#1082;&amp;#1072;&lt;/font&gt;&lt;br&gt;&lt;font color="#0000ff" &gt;public&lt;/font&gt;&lt;font color="#000000" &gt;:&lt;/font&gt;&lt;br&gt;  &lt;font color="#000000" &gt;wrapper(T&amp;amp;&lt;/font&gt; &lt;font color="#000000" &gt;t)&lt;/font&gt; &lt;font color="#000000" &gt;:&lt;/font&gt; &lt;font color="#000000" &gt;t_(t)&lt;/font&gt; &lt;font color="#000000" &gt;{}&lt;/font&gt; &lt;font color="#008000" &gt;// &amp;#1085;&amp;#1077;&amp;#1103;&amp;#1074;&amp;#1085;&amp;#1099;&amp;#1081; &amp;#1082;&amp;#1086;&amp;#1085;&amp;#1089;&amp;#1090;&amp;#1088;&amp;#1091;&amp;#1082;&amp;#1090;&amp;#1086;&amp;#1088; &amp;#1080;&amp;#1079; T&lt;/font&gt;&lt;br&gt;  &lt;font color="#0000ff" &gt;operator&lt;/font&gt; &lt;font color="#000000" &gt;T&amp;amp;()&lt;/font&gt; &lt;font color="#0000ff" &gt;const&lt;/font&gt; &lt;font color="#000000" &gt;{&lt;/font&gt; &lt;font color="#0000ff" &gt;return&lt;/font&gt; &lt;font color="#000000" &gt;t_;&lt;/font&gt; &lt;font color="#000000" &gt;}&lt;/font&gt; &lt;font color="#008000" &gt;// &amp;#1085;&amp;#1077;&amp;#1103;&amp;#1074;&amp;#1085;&amp;#1086;&amp;#1077; &amp;#1087;&amp;#1088;&amp;#1077;&amp;#1086;&amp;#1073;&amp;#1088;&amp;#1072;&amp;#1079;&amp;#1086;&amp;#1074;&amp;#1072;&amp;#1085;&amp;#1080;&amp;#1077; &amp;#1082; T&amp;amp;&lt;/font&gt;&lt;br&gt;&lt;font color="#000000" &gt;};&lt;/font&gt;&lt;br&gt;&lt;/font&gt;&lt;/pre&gt;&lt;/td&gt;&lt;br /&gt;Теперь &lt;b&gt;wrapper&lt;/b&gt; можно опробовать в деле. Поместим объявление этого типа в пространство имен &lt;b&gt;foo&lt;/b&gt;, туда же поместим и &lt;b&gt;operator&lt;&lt;&lt;/b&gt;. В качестве аргумента шаблона класса &lt;b&gt;std::ostream_iterator&lt;/b&gt; укажем &lt;b&gt;wrapper&lt;/b&gt; с &lt;b&gt;std::pair&amp;lt;const std::string, int&amp;gt;&lt;/b&gt; в качестве &lt;b&gt;T&lt;/b&gt;.&lt;br /&gt;Весь пример:&lt;br /&gt;&lt;tr&gt;&lt;td&gt;&lt;pre&gt;&lt;font color="white" face="CourierNew" size=3&gt;&lt;br&gt;&lt;font color="#0000ff" &gt;#include&lt;/font&gt; &lt;font color="#800000" &gt;&amp;lt;map&amp;gt;&lt;/font&gt;&lt;br&gt;&lt;font color="#0000ff" &gt;#include&lt;/font&gt; &lt;font color="#800000" &gt;&amp;lt;string&amp;gt;&lt;/font&gt;&lt;br&gt;&lt;font color="#0000ff" &gt;#include&lt;/font&gt; &lt;font color="#800000" &gt;&amp;lt;iostream&amp;gt;&lt;/font&gt;&lt;br&gt;&lt;br&gt;&lt;font color="#0000ff" &gt;namespace&lt;/font&gt; &lt;font color="#000000" &gt;foo&lt;/font&gt;&lt;br&gt;&lt;font color="#000000" &gt;{&lt;/font&gt;&lt;br&gt;&lt;br&gt;  &lt;font color="#0000ff" &gt;template&lt;/font&gt; &lt;font color="#000000" &gt;&amp;lt;&lt;/font&gt;&lt;font color="#0000ff" &gt;class&lt;/font&gt; &lt;font color="#000000" &gt;T&amp;gt;&lt;/font&gt;&lt;br&gt;  &lt;font color="#0000ff" &gt;class&lt;/font&gt; &lt;font color="#000000" &gt;wrapper&lt;/font&gt;&lt;br&gt;  &lt;font color="#000000" &gt;{&lt;/font&gt;&lt;br&gt;    &lt;font color="#000000" &gt;T&amp;amp;&lt;/font&gt; &lt;font color="#000000" &gt;t_;&lt;/font&gt;&lt;br&gt;  &lt;font color="#0000ff" &gt;public&lt;/font&gt;&lt;font color="#000000" &gt;:&lt;/font&gt;&lt;br&gt;    &lt;font color="#000000" &gt;wrapper(T&amp;amp;&lt;/font&gt; &lt;font color="#000000" &gt;t)&lt;/font&gt; &lt;font color="#000000" &gt;:&lt;/font&gt; &lt;font color="#000000" &gt;t_(t)&lt;/font&gt; &lt;font color="#000000" &gt;{}&lt;/font&gt;&lt;br&gt;    &lt;font color="#0000ff" &gt;operator&lt;/font&gt; &lt;font color="#000000" &gt;T&amp;amp;()&lt;/font&gt; &lt;font color="#0000ff" &gt;const&lt;/font&gt; &lt;font color="#000000" &gt;{&lt;/font&gt; &lt;font color="#0000ff" &gt;return&lt;/font&gt; &lt;font color="#000000" &gt;t_;&lt;/font&gt; &lt;font color="#000000" &gt;}&lt;/font&gt;&lt;br&gt;  &lt;font color="#000000" &gt;};&lt;/font&gt;&lt;br&gt;&lt;br&gt;  &lt;font color="#000000" &gt;std::ostream&amp;amp;&lt;/font&gt; &lt;font color="#0000ff" &gt;operator&lt;/font&gt;&lt;font color="#000000" &gt;&amp;lt;&amp;lt;&lt;/font&gt; &lt;font color="#000000" &gt;(std::ostream&amp;amp;&lt;/font&gt; &lt;font color="#000000" &gt;str,&lt;/font&gt;&lt;br&gt;    &lt;font color="#000000" &gt;std::pair&amp;lt;&lt;/font&gt;&lt;font color="#0000ff" &gt;const&lt;/font&gt; &lt;font color="#000000" &gt;std::string,&lt;/font&gt; &lt;font color="#0000ff" &gt;int&lt;/font&gt;&lt;font color="#000000" &gt;&amp;gt;&lt;/font&gt; &lt;font color="#0000ff" &gt;const&lt;/font&gt;&lt;font color="#000000" &gt;&amp;amp;&lt;/font&gt; &lt;font color="#000000" &gt;val)&lt;/font&gt;&lt;br&gt;  &lt;font color="#000000" &gt;{&lt;/font&gt;&lt;br&gt;    &lt;font color="#000000" &gt;str&lt;/font&gt; &lt;font color="#000000" &gt;&amp;lt;&amp;lt;&lt;/font&gt; &lt;font color="#000000" &gt;val.first&lt;/font&gt; &lt;font color="#000000" &gt;&amp;lt;&amp;lt;&lt;/font&gt; &lt;font color="#800000" &gt;" = "&lt;/font&gt; &lt;font color="#000000" &gt;&amp;lt;&amp;lt;&lt;/font&gt; &lt;font color="#000000" &gt;val.second&lt;/font&gt; &lt;font color="#000000" &gt;&amp;lt;&amp;lt;&lt;/font&gt; &lt;font color="#000000" &gt;std::endl;&lt;/font&gt;&lt;br&gt;    &lt;font color="#0000ff" &gt;return&lt;/font&gt; &lt;font color="#000000" &gt;str;&lt;/font&gt;&lt;br&gt;  &lt;font color="#000000" &gt;}&lt;/font&gt;&lt;br&gt;&lt;br&gt;&lt;font color="#000000" &gt;}&lt;/font&gt; &lt;font color="#008000" &gt;// namespace foo&lt;/font&gt;&lt;br&gt;&lt;br&gt;&lt;font color="#0000ff" &gt;int&lt;/font&gt; &lt;font color="#000000" &gt;main()&lt;/font&gt;&lt;br&gt;&lt;font color="#000000" &gt;{&lt;/font&gt;&lt;br&gt;  &lt;font color="#000000" &gt;std::multimap&amp;lt;std::string,&lt;/font&gt; &lt;font color="#0000ff" &gt;int&lt;/font&gt;&lt;font color="#000000" &gt;&amp;gt;&lt;/font&gt; &lt;font color="#000000" &gt;int_map;&lt;/font&gt;&lt;br&gt;  &lt;font color="#000000" &gt;int_map.insert(std::make_pair(&lt;/font&gt;&lt;font color="#800000" &gt;"foo"&lt;/font&gt;&lt;font color="#000000" &gt;,&lt;/font&gt; &lt;font color="#000000" &gt;1));&lt;/font&gt;&lt;br&gt;  &lt;font color="#000000" &gt;int_map.insert(std::make_pair(&lt;/font&gt;&lt;font color="#800000" &gt;"foo"&lt;/font&gt;&lt;font color="#000000" &gt;,&lt;/font&gt; &lt;font color="#000000" &gt;2));&lt;/font&gt;&lt;br&gt;&lt;br&gt;  &lt;font color="#0000ff" &gt;typedef&lt;/font&gt; &lt;font color="#000000" &gt;foo::wrapper&amp;lt;&lt;/font&gt; &lt;font color="#000000" &gt;std::pair&amp;lt;&lt;/font&gt;&lt;font color="#0000ff" &gt;const&lt;/font&gt; &lt;font color="#000000" &gt;std::string,&lt;/font&gt; &lt;font color="#0000ff" &gt;int&lt;/font&gt;&lt;font color="#000000" &gt;&amp;gt;&lt;/font&gt; &lt;font color="#000000" &gt;&amp;gt;&lt;/font&gt; &lt;font color="#000000" &gt;pair_wrapper;&lt;/font&gt;&lt;br&gt;  &lt;font color="#000000" &gt;std::copy(int_map.begin(),&lt;/font&gt; &lt;font color="#000000" &gt;int_map.end(),&lt;/font&gt;&lt;br&gt;    &lt;font color="#000000" &gt;std::ostream_iterator&amp;lt;pair_wrapper&amp;gt;(std::cout));&lt;/font&gt;&lt;br&gt;&lt;font color="#000000" &gt;}&lt;/font&gt;&lt;/font&gt;&lt;/pre&gt;&lt;/td&gt;&lt;br /&gt;Замечательно, все работает так, как и требовалось, а &lt;b&gt;operator&lt;&lt;&lt;/b&gt; вынесен из пространства имен &lt;b&gt;std&lt;/b&gt;!&lt;br /&gt;&lt;br /&gt;Остается только уточнить небольшой ньюанс. Может появиться желание сделать &lt;b&gt;wrapper&lt;/b&gt; еще более универсальным вынеся его в некоторое другое пространство имен, например &lt;b&gt;common&lt;/b&gt;, для удобстра использования в случае повторного применения. В &lt;b&gt;foo&lt;/b&gt; же при помощи &lt;b&gt;typedef&lt;/b&gt; объявить псевдоним &lt;b&gt;wrapper&lt;/b&gt;, инстанцируя его для конкретного типа.&lt;br /&gt;&lt;br /&gt;Делать этого нельзя, поскольку поиск будет проведен только в пространстве имен в котором объявлен &lt;b&gt;wrapper&lt;/b&gt;. Пространства имен его псевдонимов при поиске имен рассмотрены не будут.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/32334553-115657213071642741?l=zubankov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zubankov.blogspot.com/feeds/115657213071642741/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=32334553&amp;postID=115657213071642741' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32334553/posts/default/115657213071642741'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32334553/posts/default/115657213071642741'/><link rel='alternate' type='text/html' href='http://zubankov.blogspot.com/2006/08/adl.html' title='ADL в деле'/><author><name>Григорий Зубанков</name><uri>http://www.blogger.com/profile/11175792768984667084</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://sura.ru/ss/greg/IMG_1790_mod.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32334553.post-115641341263212855</id><published>2006-08-24T11:58:00.000+04:00</published><updated>2006-08-24T13:58:03.810+04:00</updated><title type='text'>Особенности поиска имен</title><content type='html'>В предыдущем посте "Контейнеры с эквивалентным ключем" я упростил пример вывода на экран элементов &lt;b&gt;multimap&lt;/b&gt;, добавив перегрузку &lt;b&gt;operator&lt;&lt;&lt;/b&gt; в пространство имен &lt;b&gt;std&lt;/b&gt;. Тем самым несколько покривил душой, ибо стандарт явно запрещает подобные эксперименты (см. 17.4.3.1).&lt;br /&gt;&lt;br /&gt;Давайте еще раз взглянем на пример и выясним первопричину вынудившую меня так поступить.&lt;br /&gt;Ключевые моменты примера из предыдушего поста:&lt;br /&gt;&lt;tr&gt;&lt;td&gt;&lt;pre&gt;&lt;font color="white" face="CourierNew" size=3&gt;&lt;br&gt;&lt;font color="#0000ff" &gt;namespace&lt;/font&gt; &lt;font color="#000000" &gt;std&lt;/font&gt;&lt;br&gt;&lt;font color="#000000" &gt;{&lt;/font&gt;&lt;br&gt;&lt;br&gt;  &lt;font color="#000000" &gt;std::ostream&amp;amp;&lt;/font&gt; &lt;font color="#0000ff" &gt;operator&lt;/font&gt;&lt;font color="#000000" &gt;&amp;lt;&amp;lt;(std::ostream&amp;amp;&lt;/font&gt; &lt;font color="#000000" &gt;str,&lt;/font&gt;&lt;br&gt;    &lt;font color="#000000" &gt;std::pair&amp;lt;std::string,&lt;/font&gt; &lt;font color="#0000ff" &gt;int&lt;/font&gt;&lt;font color="#000000" &gt;&amp;gt;&lt;/font&gt; &lt;font color="#0000ff" &gt;const&lt;/font&gt;&lt;font color="#000000" &gt;&amp;amp;&lt;/font&gt; &lt;font color="#000000" &gt;val);&lt;/font&gt;&lt;br&gt;&lt;br&gt;&lt;font color="#000000" &gt;}&lt;/font&gt; &lt;font color="#008000" &gt;// namespace std&lt;/font&gt;&lt;br&gt;&lt;br&gt;&lt;font color="#0000ff" &gt;int&lt;/font&gt; &lt;font color="#000000" &gt;main()&lt;/font&gt;&lt;br&gt;&lt;font color="#000000" &gt;{&lt;/font&gt;&lt;br&gt;  &lt;font color="#008000" &gt;// ...&lt;/font&gt;&lt;br&gt;  &lt;font color="#000000" &gt;std::copy(int_map.begin(),&lt;/font&gt; &lt;font color="#000000" &gt;int_map.end(),&lt;/font&gt;&lt;br&gt;    &lt;font color="#000000" &gt;std::ostream_iterator&amp;lt;&lt;/font&gt;&lt;br&gt;    &lt;font color="#000000" &gt;std::pair&amp;lt;std::string,&lt;/font&gt; &lt;font color="#0000ff" &gt;int&lt;/font&gt;&lt;font color="#000000" &gt;&amp;gt;&lt;/font&gt; &lt;font color="#000000" &gt;&amp;gt;(std::cout));&lt;/font&gt;&lt;br&gt;&lt;font color="#000000" &gt;}&lt;/font&gt;&lt;/font&gt;&lt;/pre&gt;&lt;/td&gt;&lt;br /&gt;Как компилятор найдет перегрузку &lt;b&gt;operator&lt;&lt;&lt;/b&gt; из примера? Ключевое слово - поиск имен: &lt;i&gt;Ordinary Lookup&lt;/i&gt; (&lt;b&gt;OL&lt;/b&gt;) и &lt;i&gt;Argument-Dependent Lookup&lt;/i&gt; (&lt;b&gt;ADL&lt;/b&gt;).&lt;br /&gt;&lt;br /&gt;Согласно &lt;b&gt;OL&lt;/b&gt;, встретив неквалифицированное имя, компилятор произведет поиск в той области видимости,в которой оно ему встретилось. В нашем случае это области видимости класса (&lt;i&gt;class-scope&lt;/i&gt;) &lt;b&gt;ostream_iterator&lt;/b&gt;, в &lt;b&gt;operator=&lt;/b&gt; которого и вызывается перегружаемый нами &lt;b&gt;operator&lt;&lt;&lt;/b&gt;, и пространство имен &lt;b&gt;std&lt;/b&gt;, поскольку именно в нем находится объявление &lt;b&gt;ostream_iterator&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;Если компилятор не найдет подходящего &lt;b&gt;operator&lt;&lt;&lt;/b&gt; согласно &lt;b&gt;OL&lt;/b&gt;, поиск продолжится с использованием &lt;b&gt;ADL&lt;/b&gt;. Несколько упрощая скажу, что &lt;b&gt;ADL&lt;/b&gt; предполагает поиск имен в пространствах имен типов агрументов анализируемого выражения. Типами аргументами при вызове &lt;b&gt;operator&lt;&lt;&lt;/b&gt; являются &lt;b&gt;std::ostream&lt;/b&gt; и &lt;b&gt;std::pair&lt;&gt;&lt;/b&gt;.&lt;br /&gt;Другими словами поиск подходящего &lt;b&gt;operator&lt;&lt;&lt;/b&gt; будет снова произведен в пространстве имен &lt;b&gt;std&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;Подитожу. Компилятор сможет найти перегрузку &lt;b&gt;operator&lt;&lt;&lt;/b&gt; в области видимости класса &lt;b&gt;ostream_iterator&lt;/b&gt; и пространстве имен &lt;b&gt;std&lt;/b&gt;. Поскольку определение класса &lt;b&gt;ostream_iterator&lt;/b&gt; мы изменить не в состоянии, остается только добавить перегрузку в &lt;b&gt;std&lt;/b&gt;. Что я и сделал в примере.&lt;br /&gt;&lt;br /&gt;В следующем посте я расскажу о том, как избежать внесения &lt;b&gt;operator&lt;&lt;&lt;/b&gt; в пространство имен &lt;b&gt;std&lt;/b&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/32334553-115641341263212855?l=zubankov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zubankov.blogspot.com/feeds/115641341263212855/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=32334553&amp;postID=115641341263212855' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32334553/posts/default/115641341263212855'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32334553/posts/default/115641341263212855'/><link rel='alternate' type='text/html' href='http://zubankov.blogspot.com/2006/08/blog-post_24.html' title='Особенности поиска имен'/><author><name>Григорий Зубанков</name><uri>http://www.blogger.com/profile/11175792768984667084</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://sura.ru/ss/greg/IMG_1790_mod.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32334553.post-115556371906958069</id><published>2006-08-14T17:45:00.000+04:00</published><updated>2006-08-15T11:34:02.706+04:00</updated><title type='text'>Контейнеры с эквивалентным ключом</title><content type='html'>Стоит помнить, что стандарт не дает гарантии перебора элементов с эквивалентным ключем в порядке их вставки в контейнер (&lt;b&gt;multimap&lt;/b&gt;, &lt;b&gt;multiset&lt;/b&gt;).&lt;br /&gt;Т.е. тот порядок, в котором следующий код выведет на экран список элементов в &lt;b&gt;multimap&lt;/b&gt; не определен, и зависит от вендора:&lt;br /&gt;&lt;tr&gt;&lt;td&gt;&lt;pre&gt;&lt;font color="white" face="CourierNew" size=3&gt;&lt;br&gt;&lt;font color="#0000ff" &gt;#include&lt;/font&gt; &lt;font color="#800000" &gt;&amp;lt;map&amp;gt;&lt;/font&gt;&lt;br&gt;&lt;font color="#0000ff" &gt;#include&lt;/font&gt; &lt;font color="#800000" &gt;&amp;lt;string&amp;gt;&lt;/font&gt;&lt;br&gt;&lt;font color="#0000ff" &gt;#include&lt;/font&gt; &lt;font color="#800000" &gt;&amp;lt;iostream&amp;gt;&lt;/font&gt;&lt;br&gt;&lt;br&gt;&lt;font color="#0000ff" &gt;namespace&lt;/font&gt; &lt;font color="#000000" &gt;std&lt;/font&gt;&lt;br&gt;&lt;font color="#000000" &gt;{&lt;/font&gt;&lt;br&gt;&lt;br&gt;  &lt;font color="#000000" &gt;std::ostream&amp;amp;&lt;/font&gt; &lt;font color="#0000ff" &gt;operator&lt;/font&gt;&lt;font color="#000000" &gt;&amp;lt;&amp;lt;(std::ostream&amp;amp;&lt;/font&gt; &lt;font color="#000000" &gt;str,&lt;/font&gt;&lt;br&gt;    &lt;font color="#000000" &gt;std::pair&amp;lt;std::string,&lt;/font&gt; &lt;font color="#0000ff" &gt;int&lt;/font&gt;&lt;font color="#000000" &gt;&amp;gt;&lt;/font&gt; &lt;font color="#0000ff" &gt;const&lt;/font&gt;&lt;font color="#000000" &gt;&amp;amp;&lt;/font&gt; &lt;font color="#000000" &gt;val)&lt;/font&gt;&lt;br&gt;  &lt;font color="#000000" &gt;{&lt;/font&gt;&lt;br&gt;    &lt;font color="#000000" &gt;str&lt;/font&gt; &lt;font color="#000000" &gt;&amp;lt;&amp;lt;&lt;/font&gt; &lt;font color="#000000" &gt;val.first&lt;/font&gt; &lt;font color="#000000" &gt;&amp;lt;&amp;lt;&lt;/font&gt; &lt;font color="#800000" &gt;" = "&lt;/font&gt; &lt;font color="#000000" &gt;&amp;lt;&amp;lt;&lt;/font&gt; &lt;font color="#000000" &gt;val.second&lt;/font&gt; &lt;font color="#000000" &gt;&amp;lt;&amp;lt;&lt;/font&gt; &lt;font color="#000000" &gt;std::endl;&lt;/font&gt;&lt;br&gt;    &lt;font color="#0000ff" &gt;return&lt;/font&gt; &lt;font color="#000000" &gt;str;&lt;/font&gt;&lt;br&gt;  &lt;font color="#000000" &gt;}&lt;/font&gt;&lt;br&gt;&lt;br&gt;&lt;font color="#000000" &gt;}&lt;/font&gt; &lt;font color="#008000" &gt;// namespace std&lt;/font&gt;&lt;br&gt;&lt;br&gt;&lt;font color="#0000ff" &gt;int&lt;/font&gt; &lt;font color="#000000" &gt;main()&lt;/font&gt;&lt;br&gt;&lt;font color="#000000" &gt;{&lt;/font&gt;&lt;br&gt;  &lt;font color="#000000" &gt;std::multimap&amp;lt;std::string,&lt;/font&gt; &lt;font color="#0000ff" &gt;int&lt;/font&gt;&lt;font color="#000000" &gt;&amp;gt;&lt;/font&gt; &lt;font color="#000000" &gt;int_map;&lt;/font&gt;&lt;br&gt;  &lt;font color="#000000" &gt;int_map.insert(std::make_pair(&lt;/font&gt;&lt;font color="#800000" &gt;"foo"&lt;/font&gt;&lt;font color="#000000" &gt;,&lt;/font&gt; &lt;font color="#000000" &gt;1));&lt;/font&gt;&lt;br&gt;  &lt;font color="#000000" &gt;int_map.insert(std::make_pair(&lt;/font&gt;&lt;font color="#800000" &gt;"foo"&lt;/font&gt;&lt;font color="#000000" &gt;,&lt;/font&gt; &lt;font color="#000000" &gt;2));&lt;/font&gt;&lt;br&gt;&lt;br&gt;  &lt;font color="#000000" &gt;std::copy(int_map.begin(),&lt;/font&gt; &lt;font color="#000000" &gt;int_map.end(),&lt;/font&gt;&lt;br&gt;    &lt;font color="#000000" &gt;std::ostream_iterator&amp;lt;&lt;/font&gt;&lt;br&gt;    &lt;font color="#000000" &gt;std::pair&amp;lt;std::string,&lt;/font&gt; &lt;font color="#0000ff" &gt;int&lt;/font&gt;&lt;font color="#000000" &gt;&amp;gt;&lt;/font&gt; &lt;font color="#000000" &gt;&amp;gt;(std::cout));&lt;/font&gt;&lt;br&gt;&lt;font color="#000000" &gt;}&lt;/font&gt;&lt;/font&gt;&lt;/pre&gt;&lt;/td&gt;Некоторые вендоры дают подобную гарантию, тогда закладка на порядок перебора делает Ваш код хотя и корректным, но непереносимым.&lt;br /&gt;К примеру код скомпилированный &lt;b&gt;VS2005&lt;/b&gt; c библиотекой &lt;b&gt;STL&lt;/b&gt; по умолчанию, выводит на экран элементы в порядке их вставки к контейнер:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;foo = 1&lt;br /&gt;foo = 2&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Повторю еще раз, не стоит на это закладываться. Стандарт &lt;b&gt;не гарантирует&lt;/b&gt; порядка вывода элеметнов в такой последовательности.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/32334553-115556371906958069?l=zubankov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zubankov.blogspot.com/feeds/115556371906958069/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=32334553&amp;postID=115556371906958069' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32334553/posts/default/115556371906958069'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32334553/posts/default/115556371906958069'/><link rel='alternate' type='text/html' href='http://zubankov.blogspot.com/2006/08/blog-post_14.html' title='Контейнеры с эквивалентным ключом'/><author><name>Григорий Зубанков</name><uri>http://www.blogger.com/profile/11175792768984667084</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://sura.ru/ss/greg/IMG_1790_mod.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32334553.post-115523995154904775</id><published>2006-08-10T23:47:00.000+04:00</published><updated>2006-08-11T00:05:21.246+04:00</updated><title type='text'>Указатель на функцию-член класса в качестве параметра шаблона класса</title><content type='html'>  В языке C++ cуществуют три вида параметров шаблонов (не путать с агрументами шаблонов, т.е. значениями, которые подставляются вместо параметров шаблона при инстанцировании шаблона).&lt;br/&gt;&lt;ol&gt;&lt;li&gt;&lt;i&gt;Параметры типа&lt;/i&gt;&lt;br/&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;Параметры не являющиеся типами&lt;/i&gt;&lt;br/&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;Шаблонные параметры шаблонов&lt;/i&gt;&lt;br/&gt;&lt;/li&gt;&lt;/ol&gt;  Сегодня я бы хотел остановиться подробнее на &lt;i&gt;параметрах не являющихся типами&lt;/i&gt;.&lt;br/&gt;Не так часто используемые, как &lt;i&gt;параметры типа&lt;/i&gt;, они, тем не менее, позволяют создавать интересные конструкции.&lt;br/&gt;  &lt;i&gt;Не являющиеся типами параметры&lt;/i&gt; - это константные значения, которые могут быть определены при компиляции или при компоновке.&lt;br/&gt;&lt;br/&gt;Одним из типов такого параметра (т.е. типов значений, которые они обозначают) может быть тип указателя на функцию-член класса, который и заслужил отдельной темы.&lt;br/&gt;&lt;br/&gt;Следующий пример демонстрирует технику использования указателя на функцию-член класса в качестве параметров шаблонов класса. Я поочередно приведу код каждого класса и функции примера:&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;Mutex&lt;/strong&gt; - класс, представляющий некоторый объект межпроцессной синхронизации Mutex.&lt;br/&gt;Его функции-члены позволяют захватить mutex (&lt;strong&gt;Lock&lt;/strong&gt;) и освободить его (&lt;strong&gt;Unlock&lt;/strong&gt;).&lt;br/&gt;&lt;code&gt;&lt;br/&gt;struct Mutex&lt;br/&gt;{&lt;br/&gt;  void Lock() {}&lt;br/&gt;  void Unlock() {}&lt;br/&gt;};&lt;br/&gt;&lt;/code&gt;&lt;br/&gt;&lt;strong&gt;Locker&lt;/strong&gt; - класс автоматического управления &lt;strong&gt;Mutex&lt;/strong&gt;.&lt;br/&gt;В конструкторе объект &lt;strong&gt;Mutex&lt;/strong&gt; захватывается, а в деструкторе - освобождается.&lt;br/&gt;&lt;code&gt;&lt;br/&gt;struct Locker&lt;br/&gt;{&lt;br/&gt;  Locker(Mutex&amp; m) : m_(m) { m_.Lock(); }&lt;br/&gt;  ~Locker() { m_.Unlock(); }&lt;br/&gt;  Mutex&amp; m_;&lt;br/&gt;};&lt;br/&gt;&lt;/code&gt;&lt;br/&gt;&lt;strong&gt;Unlocker&lt;/strong&gt; - класс автоматического управления &lt;strong&gt;Mutex&lt;/strong&gt; обратный &lt;strong&gt;Locker&lt;/strong&gt;.&lt;strong&gt;&lt;/strong&gt;&lt;br/&gt;В конструкторе объект &lt;strong&gt;Mutex&lt;/strong&gt; освобождается, а в деструкторе - захватывается.&lt;br/&gt;&lt;code&gt;&lt;br/&gt;struct Unlocker&lt;br/&gt;{&lt;br/&gt;  Unlocker(Mutex&amp; m) : m_(m) { m_.Unlock(); }&lt;br/&gt;  ~Unlocker() { m_.Lock(); }&lt;br/&gt;  Mutex&amp; m_;&lt;br/&gt;};&lt;br/&gt;&lt;/code&gt;&lt;br/&gt;Использование симбиоза &lt;strong&gt;Mutex&lt;/strong&gt; и &lt;strong&gt;Locker&lt;/strong&gt; тривиально:&lt;br/&gt;&lt;code&gt;&lt;br/&gt;void foo(Mutex&amp; m)&lt;br/&gt;{&lt;br/&gt;  Locker locker(m);&lt;br/&gt;  // безопасный код;&lt;br/&gt;}&lt;br/&gt;&lt;/code&gt;&lt;br/&gt;А теперь вглядитесь в классы &lt;strong&gt;Locker&lt;/strong&gt; и &lt;strong&gt;Unlocker&lt;/strong&gt;. Их код не кажется вам похожим?&lt;br/&gt;Если ли возможность обобщить код в некоторый шаблон класса и тем самым избежать дублирования?&lt;br/&gt;Ответ - да. Воспользуемся указателями на функцию-член класса в качестве шаблона класса&lt;br/&gt;Вот, чтополучается в итоге:&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;LockerT&lt;/strong&gt; - шаблон класса, вызывающий в конструкторе функцию по адресу &lt;strong&gt;Do&lt;/strong&gt; для переданного объекта типа &lt;strong&gt;Т&lt;/strong&gt;, и вызывающий в деструкторе функцию по адресу &lt;strong&gt;Undo&lt;/strong&gt; для этого же объекта.&lt;br/&gt;&lt;strong&gt;void(T::*)(void) &lt;/strong&gt;- тип функции-члена класса &lt;strong&gt;T&lt;/strong&gt;, без параметров и возвращающая &lt;strong&gt;void.&lt;/strong&gt;&lt;br/&gt;Обратите внимание на дополнительные скобки при вызове функции-члена класса по указателю. Таков синтаксис подбных вызовов в языке.&lt;br/&gt;&lt;code&gt;&lt;br/&gt;template &amp;#60;class T, void(T::*Do)(void), void(T::*Undo)(void)&amp;#62; struct LockerT&lt;br/&gt;{&lt;br/&gt;  LockerT(T&amp; m) : m_(m) { ((m_).*Do)(); }&lt;br/&gt;  ~LockerT() { ((m_).*Undo)(); }&lt;br/&gt;  T&amp; m_;&lt;br/&gt;};&lt;br/&gt;&lt;/code&gt;&lt;br/&gt;Осталось только объявить типы локеров с конкретными аргументами.&lt;br/&gt;&lt;code&gt;&lt;br/&gt;typedef LockerT&amp;#60;Mutex, &amp;Mutex::Unlock, &amp;Mutex::Lock&amp;#62; Locker;&lt;br/&gt;typedef LockerT&amp;#60;Mutex, &amp;Mutex::Lock, &amp;Mutex::Unlock&amp;#62; Unlocker;&lt;br/&gt;&lt;/code&gt;&lt;br/&gt;И можно использовать как раньше:&lt;br/&gt;&lt;code&gt;&lt;br/&gt;void foo(Mutex&amp; m)&lt;br/&gt;{&lt;br/&gt;  Locker locker(m);&lt;br/&gt;  // безопасный код;&lt;br/&gt;}&lt;br/&gt;&lt;/code&gt;&lt;br/&gt;Помимо того, что получилось избежать дублирования кода, упрощается процесс создания локеров для других объектов синхронизации (и не только).&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;CriticalSection&lt;/strong&gt; - класс, представляющий некоторый объект межпотоковой синхронизации&lt;br/&gt;Его функции-члены позволяют войти в критическую секцию (&lt;strong&gt;Enter&lt;/strong&gt;) и выйти из нее (&lt;strong&gt;Leave&lt;/strong&gt;).&lt;br/&gt;&lt;code&gt;&lt;br/&gt;struct CriticalSection&lt;br/&gt;{&lt;br/&gt;  void Enter() {}&lt;br/&gt;  void Leave() {}&lt;br/&gt;};&lt;br/&gt;&lt;/code&gt;&lt;br/&gt;Объявить локера для &lt;strong&gt;CriticalSection&lt;/strong&gt; с помощью &lt;strong&gt;LockerT&lt;/strong&gt; так же просто.&lt;br/&gt;&lt;code&gt;&lt;br/&gt;typedef LockerT&amp;#60;CriticalSection, &amp;CriticalSection::Enter, &amp;CriticalSection::Exit&amp;#62; CSLocker;&lt;br/&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/32334553-115523995154904775?l=zubankov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zubankov.blogspot.com/feeds/115523995154904775/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=32334553&amp;postID=115523995154904775' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32334553/posts/default/115523995154904775'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32334553/posts/default/115523995154904775'/><link rel='alternate' type='text/html' href='http://zubankov.blogspot.com/2006/08/blog-post.html' title='Указатель на функцию-член класса в качестве параметра шаблона класса'/><author><name>Григорий Зубанков</name><uri>http://www.blogger.com/profile/11175792768984667084</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://sura.ru/ss/greg/IMG_1790_mod.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32334553.post-115519264567036925</id><published>2006-08-10T10:38:00.000+04:00</published><updated>2006-08-10T13:08:03.700+04:00</updated><title type='text'>"The Most Important C++ Books...Ever" by Scott Meyers</title><content type='html'>Статья Скота Мейерса &lt;a href="http://www.artima.com/cppsource/top_cpp_books.html"&gt;The Most Important C++ Books...Ever.&lt;br /&gt;&lt;/a&gt;В ней он приводит свою версию &lt;strong&gt;5-ти&lt;/strong&gt; наиболее важных книг по C++.&lt;br /&gt;По мнению Мейерса это:&lt;strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;/strong&gt;&lt;strong&gt;&lt;/strong&gt;&lt;ol&gt;&lt;li&gt;&lt;strong&gt;The C++ Programming Language by Bjarne Stroustrup&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Effective C++ by Scott Meyers&lt;/strong&gt; &lt;li&gt;&lt;strong&gt;Design Patterns by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides&lt;/strong&gt; &lt;li&gt;&lt;strong&gt;International Standard for C++&lt;/strong&gt; &lt;li&gt;&lt;strong&gt;Modern C++ Design by Andrei Alexandrescu &lt;/strong&gt;&lt;/li&gt;&lt;/ol&gt;Интересно, что за бортом остался Саттер&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/32334553-115519264567036925?l=zubankov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zubankov.blogspot.com/feeds/115519264567036925/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=32334553&amp;postID=115519264567036925' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32334553/posts/default/115519264567036925'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32334553/posts/default/115519264567036925'/><link rel='alternate' type='text/html' href='http://zubankov.blogspot.com/2006/08/most-important-c-booksever-by-scott.html' title='&quot;The Most Important C++ Books...Ever&quot; by Scott Meyers'/><author><name>Григорий Зубанков</name><uri>http://www.blogger.com/profile/11175792768984667084</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://sura.ru/ss/greg/IMG_1790_mod.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32334553.post-115512479813243856</id><published>2006-08-09T15:51:00.000+04:00</published><updated>2006-08-09T17:20:58.890+04:00</updated><title type='text'>std::swap и ADL (часть 2, gcc)</title><content type='html'>  &lt;span style="font-size:130%;"&gt;Вариант обхода ошибки &lt;strong&gt;gcc&lt;/strong&gt;.&lt;br/&gt;&lt;/span&gt;&lt;br/&gt;   Судя по всему использование &lt;strong&gt;using std::swap&lt;/strong&gt; в функции &lt;strong&gt;test&lt;/strong&gt;, находящейся в области видимости &lt;strong&gt;foo&lt;/strong&gt; просто скрывало (&lt;strong&gt;hide&lt;/strong&gt;) объявление &lt;strong&gt;foo::swap&lt;/strong&gt;. Следствием этой ошибки компилятора и был вызов &lt;strong&gt;std::swap&lt;/strong&gt; вместо более подходящей &lt;strong&gt;foo::swap&lt;/strong&gt;.&lt;br/&gt;  Решить проблему можно использованием &lt;i&gt;using-directive&lt;/i&gt; вместо &lt;i&gt;using-declaration&lt;/i&gt;.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;void test()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;foo::bar&amp;#60;void&amp;#62; a, b;&lt;br /&gt;&amp;nbsp;&amp;nbsp;using namespace std; // вместо using std::swap;&lt;br /&gt;&amp;nbsp;&amp;nbsp;swap(a, b);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;В приведенном выше коде &lt;strong&gt;gcc&lt;/strong&gt; корректно вызывает именно &lt;strong&gt;foo::swap&lt;/strong&gt;.&lt;br/&gt;  Вот такой workaround.&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/32334553-115512479813243856?l=zubankov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zubankov.blogspot.com/feeds/115512479813243856/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=32334553&amp;postID=115512479813243856' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32334553/posts/default/115512479813243856'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32334553/posts/default/115512479813243856'/><link rel='alternate' type='text/html' href='http://zubankov.blogspot.com/2006/08/stdswap-adl-2-gcc.html' title='std::swap и ADL (часть 2, gcc)'/><author><name>Григорий Зубанков</name><uri>http://www.blogger.com/profile/11175792768984667084</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://sura.ru/ss/greg/IMG_1790_mod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32334553.post-115496488233124479</id><published>2006-08-07T18:45:00.000+04:00</published><updated>2006-08-09T17:18:25.986+04:00</updated><title type='text'>std::swap и ADL</title><content type='html'>&amp;nbsp;&amp;nbsp;В книге уважаемого мною автора Скота Мейерса "Эффективное использование С++" в правиле 25 даются рекомендация по использованию &lt;strong&gt;std::swap&lt;/strong&gt;.&lt;br /&gt;Это очень правильные рекомендации, им стоит придерживаться. Вот только жизнь часто вносит свои коррективы в теорию.&lt;br /&gt;&amp;nbsp;&amp;nbsp;Мейерс рассуждает о возможных действиях, когда необходимо как бы &lt;i&gt;частично специализировать&lt;/i&gt; &lt;strong&gt;std::swap&lt;/strong&gt;. "Как бы" из-за того, что частичная специализация функций в &lt;strong&gt;C++&lt;/strong&gt; и перегрузка функций в &lt;strong&gt;std::&lt;/strong&gt; запрещена стандартом.&lt;br /&gt;&amp;nbsp;&amp;nbsp;Что же делать, рассуждает он, если по-прежнему нужен способ, чтобы разрешить другим людям вызывать &lt;strong&gt;swap&lt;/strong&gt; и иметь более эффективную шаблонную версию?&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;В результате он принимает решение об объявлении функции &lt;strong&gt;swap&lt;/strong&gt; в той же области видимости что и тип, являющийся ее аргументом. Вызов &lt;strong&gt;swap&lt;/strong&gt; же не квалифицировать и поместить перед ним объявление &lt;strong&gt;using std::swap&lt;/strong&gt;. Когда компилятор встречает вызов &lt;strong&gt;swap&lt;/strong&gt;, он ищет, какую версию вызвать.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;namespace foo&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;template &amp;#60;class T&amp;#62; class bar {};&lt;br /&gt;&amp;nbsp;&amp;nbsp;template &amp;#60;class T&amp;#62; void swap(bar&amp;#60;T&amp;#62;&amp;, bar&amp;#60;T&amp;#62;&amp;) {}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void test()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;foo::bar&amp;#60;void&amp;#62; a, b;&lt;br /&gt;&amp;nbsp;&amp;nbsp;using std::swap;&lt;br /&gt;&amp;nbsp;&amp;nbsp;swap(a, b);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;Следуя правилам разрешения имен в &lt;strong&gt;С++&lt;/strong&gt; (используется &lt;strong&gt;ADL&lt;/strong&gt;) будет найдена шаблонная функция &lt;strong&gt;foo::swap&lt;/strong&gt;. При ее отсутствии будет вызвана шаблонная функция &lt;strong&gt;std::swap&lt;/strong&gt;.&lt;br/&gt;Стандарт 3.4.2 стих 2а.&lt;br/&gt;&lt;br/&gt;    Итак, казалось бы жизнь прекрасна, проблема решена. Но не тут то было. &lt;i&gt;Чудовищные&lt;/i&gt; нюансы поджидают нас в компиляторе &lt;strong&gt;gcc&lt;/strong&gt;. Стоит лишь поместить функции &lt;strong&gt;test&lt;/strong&gt; в ту же область видимости что и &lt;strong&gt;swap&lt;/strong&gt; (в примере &lt;strong&gt;foo&lt;/strong&gt;) и код сгенерированный &lt;strong&gt;gcc&lt;/strong&gt; вызовет &lt;strong&gt;std::swap&lt;/strong&gt; вместо &lt;strong&gt;foo::swap&lt;/strong&gt;.&lt;br/&gt;    Явная бага компилятора. Разработчики &lt;strong&gt;gcc&lt;/strong&gt; же отвечают крайне &lt;a href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21615"&gt;невнятно&lt;/a&gt;. В последней версии &lt;strong&gt;gcc&lt;/strong&gt; (на данный момент это 4.1.0) проблема по прежнему осталась.&lt;br/&gt;&lt;br/&gt;Так что острожнее.&lt;br/&gt;Beware of bugs.&lt;br/&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/32334553-115496488233124479?l=zubankov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zubankov.blogspot.com/feeds/115496488233124479/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=32334553&amp;postID=115496488233124479' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32334553/posts/default/115496488233124479'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32334553/posts/default/115496488233124479'/><link rel='alternate' type='text/html' href='http://zubankov.blogspot.com/2006/08/stdswap-adl.html' title='std::swap и ADL'/><author><name>Григорий Зубанков</name><uri>http://www.blogger.com/profile/11175792768984667084</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://sura.ru/ss/greg/IMG_1790_mod.jpg'/></author><thr:total>0</thr:total></entry></feed>
