<?xml version='1.0' encoding="utf-8"?>
      <rss version='2.0'>
      <channel>
      <title>Форум на Исходниках.RU</title>
      <link>https://forum.sources.ru</link>
      <description>Форум на Исходниках.RU</description>
      <generator>Форум на Исходниках.RU</generator>
  	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=86507&amp;view=findpost&amp;p=3056771</guid>
        <pubDate>Sun, 08 Jan 2012 14:55:27 +0000</pubDate>
        <title>Что такое traits?</title>
        <link>https://forum.sources.ru/index.php?showtopic=86507&amp;view=findpost&amp;p=3056771</link>
        <description><![CDATA[amk: На самом деле выгодность меняется когда тип имеет размер два-три регистра - зависит от количества и интенсивности использования аргументов, количества регистров в машине и стратегии их использования. То есть на границе оказывается тип вроде complex.<br><br>Причем даже для крупного аргумента может оказаться эффективнее передать его по значению.<br>Например, обращений к объекту много, но они редкие (ссылка не кешируется) - в результате при передаче по значению обращение производится напрямую, а при передаче по ссылке превращается в два, одно для выборки ссылки, другое - для обращения к данным.<br><br>В общем без явных измерений и не угадаешь, как эффективнее.]]></description>
        <author>amk</author>
        <category>C/C++ FAQ</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=86507&amp;view=findpost&amp;p=3056722</guid>
        <pubDate>Sun, 08 Jan 2012 09:03:50 +0000</pubDate>
        <title>Что такое traits?</title>
        <link>https://forum.sources.ru/index.php?showtopic=86507&amp;view=findpost&amp;p=3056722</link>
        <description><![CDATA[niXman: <div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=86507&view=findpost&p=641617'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>byte &#064; <time class="tag-quote__quoted-time" datetime="2005-03-11T19:27:44+00:00">11.03.05, 19:27</time></span><div class='quote '>эффективней передать int или char по значению, чем по константной ссылке.</div></div><br>
спорно, потому что ссылка всегда занимает регистр целиком. по этому, эффективней это только для типов разрядность которых, меньше размера регистра.<br>
<br>
<div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=86507&view=findpost&p=641617'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>byte &#064; <time class="tag-quote__quoted-time" datetime="2005-03-11T19:27:44+00:00">11.03.05, 19:27</time></span><div class='quote '>Но вдруг нам надо доработать класс так, что нужна константа вещественного типа. Но возникает такая проблема: в классах можно инициализировать только статические интегральные константы. В enum&#39;ах тоже можно использовать только целые типы. Что же тогда делать? Остается только определить inline-фунцию, которая бы возвращала нужное значение:</div></div><br>
в рамках текущего стандарта, я бы поступил так:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">#include &#60;iostream&#62;</div><div class="code_line">&nbsp;</div><div class="code_line">template &#60;typename T&#62;</div><div class="code_line">struct x_traits {</div><div class="code_line">&nbsp;static constexpr std::size_t T2 = (sizeof(T) * 4);</div><div class="code_line">&nbsp;static constexpr std::size_t T3 = (sizeof(T) * 2);</div><div class="code_line">&nbsp;static constexpr std::size_t T4 = (sizeof(T));</div><div class="code_line">&nbsp;static constexpr double &nbsp; &nbsp; &nbsp;T5 = (sizeof(T) * 5 / 7);</div><div class="code_line">};</div><div class="code_line">&nbsp;</div><div class="code_line">template &#60;typename T, typename traits = x_traits&#60;T&#62; &#62;</div><div class="code_line">struct X {</div><div class="code_line">&nbsp;&nbsp;// используем нужные константы через traits:</div><div class="code_line">&nbsp;&nbsp;// T2: traits::T2() - возвращает тип std::size_t, можно и через enum</div><div class="code_line">&nbsp;&nbsp;// T5: traits::T5() - возвращает тип double, по-другому не сделать, только функция</div><div class="code_line">};</div></ol></div></div></div></div><script>preloadCodeButtons('1');</script><br>
<br>
<div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=86507&view=findpost&p=3056722'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>niXman &#064; <time class="tag-quote__quoted-time" datetime="2012-01-08T09:03:50+00:00">08.01.12, 09:03</time></span><div class='quote '>спорно, потому что ссылка всегда занимает регистр целиком.</div></div><br>
хотя и это тоже спорно. ведь ссылка - всего лишь псевдоним + синтаксический сахар. как компилятор реализует ссылки, по идее, зависит от конкретного компилятора. так что не уверен.]]></description>
        <author>niXman</author>
        <category>C/C++ FAQ</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=86507&amp;view=findpost&amp;p=3053363</guid>
        <pubDate>Wed, 28 Dec 2011 18:50:47 +0000</pubDate>
        <title>Что такое traits?</title>
        <link>https://forum.sources.ru/index.php?showtopic=86507&amp;view=findpost&amp;p=3053363</link>
        <description><![CDATA[Сыроежка: <div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=86507&view=findpost&p=3053304'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>Qraizer &#064; <time class="tag-quote__quoted-time" datetime="2011-12-28T14:59:46+00:00">28.12.11, 14:59</time></span><div class='quote '>Как раз наоборот. Представив одну (первую) из возможных реализаций параметризации, он показал её слабые места, и перейдя к концепции классов свойств, показал, как они решаются. При этом получая другие слабые места, но они являются уже инкапслуированными в классе, поэтому практически не влияют на клиентский код. См. ниже.</div></div><br>
<br>
да ничего он не показал&#33; Он сначала сделал глупость, а затем определил все эти типы через <strong class='tag-b'>typedef</strong>. Спрашивается, а зачем было городить весь этот огород с первым примерома, а не сделать в нем те же самые <strong class='tag-b'>typedef</strong>?&#33;<br>
<br>
Так что статья очень слабая и нре убедительная.<br>
<br>
<div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=86507&view=findpost&p=3053304'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>Qraizer &#064; <time class="tag-quote__quoted-time" datetime="2011-12-28T14:59:46+00:00">28.12.11, 14:59</time></span><div class='quote '>Цитата (Сыроежка @ Вчера, 21:53)Просто для типа char b int можно было специализировать класс вектора.<br>
Упс. Это решение действительно предпочтительнее??</div></div><br>
<br>
Это решение, которое повсеместно используется в стандартной библиотеке С++.]]></description>
        <author>Сыроежка</author>
        <category>C/C++ FAQ</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=86507&amp;view=findpost&amp;p=3053304</guid>
        <pubDate>Wed, 28 Dec 2011 14:59:46 +0000</pubDate>
        <title>Что такое traits?</title>
        <link>https://forum.sources.ru/index.php?showtopic=86507&amp;view=findpost&amp;p=3053304</link>
        <description><![CDATA[Qraizer: <div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=86507&view=findpost&p=3052799'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>Сыроежка &#064; <time class="tag-quote__quoted-time" datetime="2011-12-27T17:53:04+00:00">27.12.11, 17:53</time></span><div class='quote '>Или автор предполагает, что тип элемента шаблона может быть одним, а тип ссылки на элемент может быть ссылкой на совершенно другой тип?&#33;</div></div>Именно. Ссылкой может служить некий прокси-класс.<div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=86507&view=findpost&p=3052799'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>Сыроежка &#064; <time class="tag-quote__quoted-time" datetime="2011-12-27T17:53:04+00:00">27.12.11, 17:53</time></span><div class='quote '>То есть получается, что читая статью, мы получаем сведения не о логически вытекающей из первого примера пользе классов свойств, а о том, что автор сначала сделал глупость, а потом свою глупость пытается исправить.</div></div>Как раз наоборот. Представив одну (первую) из возможных реализаций параметризации, он показал её слабые места, и перейдя к концепции классов свойств, показал, как они решаются. При этом получая другие слабые места, но они являются уже инкапслуированными в классе, поэтому практически не влияют на клиентский код. См. ниже.<br>
<div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=86507&view=findpost&p=3052799'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>Сыроежка &#064; <time class="tag-quote__quoted-time" datetime="2011-12-27T17:53:04+00:00">27.12.11, 17:53</time></span><div class='quote '>Просто для типа char b int можно было специализировать класс вектора.</div></div>Упс. Это решение действительно предпочтительнее??<div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=86507&view=findpost&p=3052799'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>Сыроежка &#064; <time class="tag-quote__quoted-time" datetime="2011-12-27T17:53:04+00:00">27.12.11, 17:53</time></span><div class='quote '>Сейчас же подход, предложенный автором, просто не корректный, так как вы уже не можете использовать этот класс свойств, если для типа char в другом контейнере вы хотите сохранить определения типов по умолчанию&#33;</div></div>Да, &quot;ниже&quot; - это сюда. Он не некорректный. Т.к. класс свойств сильно связан с сущностью, чьи свойства он определяет, нет ничего удивительно в том, что класс является законченным конкретным классом, и его контент должен быть пересмотрен целиком при необходимости сменить то или иное свойство сущности. С другой стороны, автор отнюдь не утверждает, что класс свойств должен являться жётским каркасом для сущности. Он показал путь, как отделить определение свойств сущности от самой сущности, улучшив тем самым инкапсуляцию. Никто не запрещает продолжить декомпозицию класса свойств, если есть желание, и это работа пользователя, а не разработчика.]]></description>
        <author>Qraizer</author>
        <category>C/C++ FAQ</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=86507&amp;view=findpost&amp;p=3052799</guid>
        <pubDate>Tue, 27 Dec 2011 17:53:04 +0000</pubDate>
        <title>Что такое traits?</title>
        <link>https://forum.sources.ru/index.php?showtopic=86507&amp;view=findpost&amp;p=3052799</link>
        <description><![CDATA[Сыроежка: <div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=86507&view=findpost&p=641617'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>byte &#064; <time class="tag-quote__quoted-time" datetime="2005-03-11T19:27:44+00:00">11.03.05, 19:27</time></span><div class='quote '>Следует заметить, что свойства также можно реализовать с помощью структуры, так как в C++ это практически аналоги. Далее я буду использовать термин класс, хотя все сказанное будет в той же мере относиться к структурам.</div></div><br>
<br>
Я автору статьи настоятельно рекомендую почитать главу 9 стандарта С++, где дается определение класса в частности лексической единицы <strong class='tag-b'>class-key</strong>. Тогда у него не будет путаницы в вопросе классов и структур.<br>
<br>
<div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=86507&view=findpost&p=641617'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>byte &#064; <time class="tag-quote__quoted-time" datetime="2005-03-11T19:27:44+00:00">11.03.05, 19:27</time></span><div class='quote '>Итак, наш шаблонный класс динамического массива должен иметь в качестве аргументов шаблона:<br>
1) тип элемента шаблона<br>
2) тип ссылки на элемент<br>
3) тип аргумента функций<br>
4) тип константной ссылки</div></div><br>
<br>
Это вообще не понятно. Во-первых, автор неправильно называет параметры шаблона аргументами. Во-вторых, не видно смысла почему тип элемента шаблона и, например, тип ссылки на элемент, должны быть заданы как отдельные параметры шаблона?&#33; Почему тип ссылки иои тип константной ссылки нельзя определить внутри класса с помощью <strong class='tag-b'>typedefr</strong> на основе параметра шаблона. Или автор предполагает, что тип элемента шаблона может быть одним, а тип ссылки на элемент может быть ссылкой на совершенно другой тип?&#33;<br>
<br>
<div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=86507&view=findpost&p=641617'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>byte &#064; <time class="tag-quote__quoted-time" datetime="2005-03-11T19:27:44+00:00">11.03.05, 19:27</time></span><div class='quote '>Думаю, прокомментировать стоит только тип аргумента функций. Этот тип используется для вставки элементов в массив. Например, эффективней передать int или char по значению, чем по константной ссылке.<br>
template </div></div><br>
<br>
Очень сомнительное высказывание, так как шаблонный массив не обязательно должен инстанцироваться только для типов <strong class='tag-b'>int</strong> или <strong class='tag-b'>char</strong>, но и для разработанных пользователем типов, например, для типа <strong class='tag-b'>std::string</strong>. Поэтому лучше не вводить ввобще такой параметр шаблона, так как это затрудняет его восприятие пользователем, а для встроенных типов сделать специализацию данного шаблона.<br>
<br>
<div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=86507&view=findpost&p=641617'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>byte &#064; <time class="tag-quote__quoted-time" datetime="2005-03-11T19:27:44+00:00">11.03.05, 19:27</time></span><div class='quote '>template &lt;typename T&gt;<br>
class elem_traits {<br>
   public:<br>
    typedef const T&amp; arg_type;<br>
    typedef       T&amp; reference;<br>
    typedef const T&amp; const_reference;<br>
};</div></div><br>
<br>
Далее автор сам себе противоречит, то есть делает несостоятельным предыдущее решение. Но только не потому, что, какуказал, для списка придется дублировать код, а потому, что в первом решении он использовал многочисленные параметры шаблона, которые совершенно излишни, а во-втором случае вместо параметров шаблона стал использовать <strong class='tag-b'>typedef</strong> на основе одного параметра шаблона, как я и предлагал делать с самого начала.<br>
То есть получается, что читая статью, мы получаем сведения не о логически вытекающей из первого примера пользе классов свойств, а о том, что автор сначала сделал глупость, а потом свою глупость пытается исправить.<br>
<br>
<div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=86507&view=findpost&p=641617'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>byte &#064; <time class="tag-quote__quoted-time" datetime="2005-03-11T19:27:44+00:00">11.03.05, 19:27</time></span><div class='quote '>Это и будет наш класс свойств. То есть он описывает те типы(arg_type, reference, const_reference), которые представляют наш тип T. Таким образом, нам надо вместо несколько аргументов шаблона писать только один дополнительный аргумент - класс свойств, который содержит в себе все нужные типы.</div></div><br>
<br>
Так и раньше можно было вместо нескольких параметров (хотел сказать неправильно за автором вместо параметров слово аргументов) шаблона задать только один параметр, а все другие типы определить с помощью <strong class='tag-b'>typedef</strong>. В чем была проблема-то?&#33;<br>
<br>
<div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=86507&view=findpost&p=641617'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>byte &#064; <time class="tag-quote__quoted-time" datetime="2005-03-11T19:27:44+00:00">11.03.05, 19:27</time></span><div class='quote '>В этом примере для всех типов используются аргументы по умолчанию. Но мы выяснили, что аргументы типа char лучше передавать не по константной ссылке, а по значению, то можно сделать специализацию нашего класса свойств:<br>
<br>
// специализация для типа char<br>
template &lt;&gt;<br>
class elem_traits&lt;char&gt; {<br>
   public:<br>
    typedef const char  arg_type; // определили тип, который передает по значению типы char<br>
    typedef       char&amp; reference;<br>
    typedef const char&amp; const_reference;<br>
};</div></div><br>
<br>
Все тоже самое можно было сделать без всякого класса свойств в первой реализации вектора. Просто для типа <strong class='tag-b'>char</strong> b <strong class='tag-b'>int</strong> можно было специализировать класс вектора.<br>
Сейчас же подход, предложенный автором, просто не корректный, так как вы уже не можете использовать этот класс свойств, если для типа <strong class='tag-b'>char</strong> в другом контейнере вы хотите сохранить определения типов по умолчанию&#33;<br>
<br>
<div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=86507&view=findpost&p=641617'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>byte &#064; <time class="tag-quote__quoted-time" datetime="2005-03-11T19:27:44+00:00">11.03.05, 19:27</time></span><div class='quote '>template &lt;typename T&gt;<br>
struct x_traits {<br>
static std::size_t T2 = sizeof(T) * 4;<br>
static std::size_t T3 = sizeof(T) * 2;<br>
static std::size_t T4 = sizeof(T);<br>
};</div></div><br>
<br>
Вообще-то, этот код нре должен компилироваться, так как объявлены не константы в виду отсутствия квалификатора <strong class='tag-b'>const</strong>, а переменные. А переменные нельзя инициализировать внутри определения класса. Возможно, что это проста опечатка автора, но тем не менее она имеет место быть.]]></description>
        <author>Сыроежка</author>
        <category>C/C++ FAQ</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=86507&amp;view=findpost&amp;p=3045909</guid>
        <pubDate>Thu, 15 Dec 2011 13:04:56 +0000</pubDate>
        <title>Что такое traits?</title>
        <link>https://forum.sources.ru/index.php?showtopic=86507&amp;view=findpost&amp;p=3045909</link>
        <description><![CDATA[spy_: <strong class='tag-b'>byte</strong>, да, у Саттера в More Exceptional C++ есть про traits. Отличная книга (обе части).]]></description>
        <author>spy_</author>
        <category>C/C++ FAQ</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=86507&amp;view=findpost&amp;p=3036665</guid>
        <pubDate>Fri, 02 Dec 2011 09:12:44 +0000</pubDate>
        <title>Что такое traits?</title>
        <link>https://forum.sources.ru/index.php?showtopic=86507&amp;view=findpost&amp;p=3036665</link>
        <description><![CDATA[DaddyM: Хорошее описание данного вопроса вы также найдёте в книге Стивена Дьюхерста (коллеги Страуструпа) &quot;С++ Священные Знания&quot; 2 изд., тема 54]]></description>
        <author>DaddyM</author>
        <category>C/C++ FAQ</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=86507&amp;view=findpost&amp;p=641617</guid>
        <pubDate>Fri, 11 Mar 2005 19:27:44 +0000</pubDate>
        <title>Что такое traits?</title>
        <link>https://forum.sources.ru/index.php?showtopic=86507&amp;view=findpost&amp;p=641617</link>
        <description><![CDATA[byte: <span class='tag-size' data-value='14' style='font-size:14pt;'>Что такое traits?</span><br>
<br>
<strong class='tag-b'><span class='tag-size' data-value='12' style='font-size:12pt;'>Вступление</span></strong><br>
В данной статье я попытаюсь рассказать, что такое traits. Будут рассмотрены некоторые примеры применения traits, которые будут заключаться как в использовании traits в нашем коде, так и в возможных способах расширения стандартной библиотеки C++, которая тоже использует traits. Также будут рассмотрены возможные проблемы, которые могут возникнуть при расширении стандартной библиотеки C++.<br>
<br>
<strong class='tag-b'><span class='tag-size' data-value='12' style='font-size:12pt;'>Для кого написана данная статья?</span></strong><br>
Эта статья написана для программистов на C++, которые уже неплохо владеют самим языком, его основными конструкциями. В частности, необходимо знание, что такое шаблоны(templates) и желателен опыт их использования. Также очень желательно знание стандартной библиотеки C++, так как многие примеры будут посвящены именно ей.<br>
<br>
<strong class='tag-b'><span class='tag-size' data-value='12' style='font-size:12pt;'>Ну, поехали...</span></strong><br>
Итак, приступим. Думаю, начать стоит с перевода термина traits. Обычно его переводят как &quot;свойства&quot;. Но traits реализуются классом, поэтому обычно употребляется термин &quot;класс свойств&quot;. Следует заметить, что свойства также можно реализовать с помощью структуры, так как в C++ это практически аналоги. Далее я буду использовать термин класс, хотя все сказанное будет в той же мере относиться к структурам.<br>
<br>
Теперь следует дать определение свойств. Натан Майерс, разработавший метод использования свойств, предложил такое определение:<br>
Класс свойств - это класс, используемый вместо параметров шаблона. В качестве класса он объединяет полезные типы и константы; как шаблон, он является средством для обеспечения того &quot;дополнительного уровня косвенности&quot;, который решает все проблемы программного обеспечения.<br>
<br>
Определение не настолько понятное, так что давайте попробуем разобраться, что же имеется в виду. Для этого предлагается рассмотреть небольшой пример. В качестве примера мы рассмотрим шаблонный класс динамического массива. Конечно, реализовывать полностью этот класс мы не будем(у нас уже есть vector), но общие концепции мы рассмотрим.<br>
Итак, наш шаблонный класс динамического массива должен иметь в качестве аргументов шаблона:<br>
1) тип элемента шаблона<br>
2) тип ссылки на элемент<br>
3) тип аргумента функций<br>
4) тип константной ссылки<br>
Думаю, прокомментировать стоит только тип аргумента функций. Этот тип используется для вставки элементов в массив. Например, эффективней передать int или char по значению, чем по константной ссылке.<br>
Тогда набросок класса будет выглядеть так:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">template &#60;typename T,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;typename ArgT &nbsp; &nbsp; &nbsp;= const T&amp;,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;typename RefT &nbsp; &nbsp; &nbsp;= T&amp;,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;typename ConstRefT = const T&amp;&#62;</div><div class="code_line">class vector {</div><div class="code_line">&nbsp;&nbsp; &nbsp; // ...</div><div class="code_line">&nbsp;&nbsp; &nbsp;public:</div><div class="code_line">&nbsp;&nbsp; &nbsp; typedef T &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; value_type;</div><div class="code_line">&nbsp;&nbsp; &nbsp; typedef ArgT &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;arg_type;</div><div class="code_line">&nbsp;&nbsp; &nbsp; typedef RefT &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;reference;</div><div class="code_line">&nbsp;&nbsp; &nbsp; typedef ConstRefT &nbsp; &nbsp; const_reference;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;void push_back(arg_type);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;// ...</div><div class="code_line">};</div></ol></div></div></div></div><br>
Для удобства были добавлены соответствующие значения параметров шаблона по умолчанию.<br>
Тогда каждый пользователь нашего класса должен будет создавать объекты класса как-то так:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">// используем параметры по умолчанию</div><div class="code_line">vector&#60;int&#62; vec1; // эквивалентно: vector&#60;int, const int&amp;, int&amp;, const int&amp;&#62;</div><div class="code_line">&nbsp;</div><div class="code_line">// переопределяем один из параметров по умолчанию</div><div class="code_line">// обратите на второй аргумент шаблона(не ссылка, а передача по значению)</div><div class="code_line">vector&#60;int, const int&#62; vec2; // эквивалентно: vector&#60;int, const int, int&amp;, const int&amp;&#62;</div><div class="code_line">&nbsp;</div><div class="code_line">// переопределяем один из параметров по умолчанию</div><div class="code_line">vector&#60;char, const char&#62; vec3; // // эквивалентно: vector&#60;char, const char, char&amp;, const char&amp;&#62;</div><div class="code_line">&nbsp;</div><div class="code_line">// используем параметры по умолчанию</div><div class="code_line">vector&#60;char&#62; vec4; // эквивалентно: vector&#60;char, const char&amp;, char&amp;, const char&amp;&#62;</div></ol></div></div></div></div><br>
Все хорошо, все отлично работает. Но если мы захотим реализовать, например, связанный список, то нам придется для него задавать аналогичные параметры шаблона. Это довольно муторно, так как придется каждый раз писать одно и то же. Тогда на помощь приходят классы свойств(traits). Создадим шаблон класса, который будет содержать все те дополнительные аргументы шаблона:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">// первичный шаблон</div><div class="code_line">// подходит в общем случае - аналог аргументов шаблона по умолчанию</div><div class="code_line">template &#60;typename T&#62;</div><div class="code_line">class elem_traits {</div><div class="code_line">&nbsp;&nbsp; &nbsp;public:</div><div class="code_line">&nbsp;&nbsp; &nbsp; typedef const T&amp; arg_type;</div><div class="code_line">&nbsp;&nbsp; &nbsp; typedef &nbsp; &nbsp; &nbsp; T&amp; reference;</div><div class="code_line">&nbsp;&nbsp; &nbsp; typedef const T&amp; const_reference;</div><div class="code_line">};</div></ol></div></div></div></div><br>
Это и будет наш класс свойств. То есть он описывает те типы(arg_type, reference, const_reference), которые представляют наш тип T. Таким образом, нам надо вместо несколько аргументов шаблона писать только один дополнительный аргумент - класс свойств, который содержит в себе все нужные типы.<br>
Тогда класс нашего динамического массива можно переписать так:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">template &#60;typename T,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;typename traits = elem_traits&#60;T&#62; &#62; // свойство по умолчанию</div><div class="code_line">class vector {</div><div class="code_line">&nbsp;&nbsp; &nbsp; // ...</div><div class="code_line">&nbsp;&nbsp; &nbsp;public:</div><div class="code_line">&nbsp;&nbsp; &nbsp; typedef T &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;value_type;</div><div class="code_line">&nbsp;&nbsp; &nbsp; typedef typename traits::arg_type &nbsp; &nbsp; &nbsp; &nbsp;arg_type;</div><div class="code_line">&nbsp;&nbsp; &nbsp; typedef typename traits::reference &nbsp; &nbsp; &nbsp; reference;</div><div class="code_line">&nbsp;&nbsp; &nbsp; typedef typename traits::const_reference const_reference;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;void push_back(arg_type);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;// ...</div><div class="code_line">};</div></ol></div></div></div></div><br>
Тогда давайте посмотрим, как пользователи нашего динамического массива будут создавать объекты:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">// используется аргумент-свойство по умолчанию</div><div class="code_line">vector&#60;int&#62; vec1; // эквивалентно: vector&#60;int, elem_traits&#60;int&#62; &#62;</div><div class="code_line">// тогда:</div><div class="code_line">// arg_type &nbsp;= const int&amp;</div><div class="code_line">// reference = int&amp;</div><div class="code_line">// const_reference = const int&amp;</div><div class="code_line">&nbsp;</div><div class="code_line">// используется аргумент-свойство по умолчанию</div><div class="code_line">vector&#60;char&#62; vec1; // эквивалентно: vector&#60;char, elem_traits&#60;char&#62; &#62;</div><div class="code_line">// тогда:</div><div class="code_line">// arg_type &nbsp;= const char&amp;</div><div class="code_line">// reference = char&amp;</div><div class="code_line">// const_reference = const char&amp;</div></ol></div></div></div></div><br>
В этом примере для всех типов используются аргументы по умолчанию. Но мы выяснили, что аргументы типа char лучше передавать не по константной ссылке, а по значению, то можно сделать специализацию нашего класса свойств:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">// специализация для типа char</div><div class="code_line">template &#60;&#62;</div><div class="code_line">class elem_traits&#60;char&#62; {</div><div class="code_line">&nbsp;&nbsp; &nbsp;public:</div><div class="code_line">&nbsp;&nbsp; &nbsp; typedef const char &nbsp;arg_type; // определили тип, который передает по значению типы char</div><div class="code_line">&nbsp;&nbsp; &nbsp; typedef &nbsp; &nbsp; &nbsp; char&amp; reference;</div><div class="code_line">&nbsp;&nbsp; &nbsp; typedef const char&amp; const_reference;</div><div class="code_line">};</div></ol></div></div></div></div><br>
Тогда объекты нашего динамического массива будем создавать так:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">vector&#60;std::string&#62; vec1; // эквивалентно: vector&#60;std::string, elem_traits&#60;std::string&#62; &#62;</div><div class="code_line">// для всех типов, для которых не сделана специализация,</div><div class="code_line">// все остается как прежде:</div><div class="code_line">// тогда:</div><div class="code_line">// arg_type &nbsp;= const std::string&amp; (по ссылке)</div><div class="code_line">// reference = std::string&amp;</div><div class="code_line">// const_reference = const std::string&amp;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;</div><div class="code_line">// а для типа char мы сделали специализацию</div><div class="code_line">vector&#60;char&#62; vec2; // эквивалентно: vector&#60;char, elem_traits&#60;char&#62; &#62;</div><div class="code_line">// тогда:</div><div class="code_line">// arg_type &nbsp;= const char (по значению, а не по ссылке)</div><div class="code_line">// reference = char&amp;</div><div class="code_line">// const_reference = const char&amp;</div></ol></div></div></div></div><br>
Давайте теперь рассмотрим случай, когда мы хотим создать динамический массив с элементами типа char, но чтобы arg_type был эквивалентен char&amp;. Специализация нашего класса elem_traits для char уже существует, то есть ее сделать мы уже не можем. В таком случае остается создать новый класс свойств:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">// обратите внимание: структура, а не класс</div><div class="code_line">// (разницы никакой, это лишний раз подчеркивается данным примером)</div><div class="code_line">struct char_elem_traits {</div><div class="code_line">&nbsp;// здесь переопределеяем тип аргумента функций.</div><div class="code_line">&nbsp;// Мы договорились, что это будет char&amp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;typedef &nbsp; &nbsp; &nbsp; char&amp; arg_type; // определили тип, который передает по ссылке типы char</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;// остальное оставляем так же.</div><div class="code_line">&nbsp;&nbsp; &nbsp;// Хотя ничто не мешает нам переопределеить тип ссылки или константной ссылки</div><div class="code_line">&nbsp;&nbsp; &nbsp;typedef &nbsp; &nbsp; &nbsp; char&amp; reference;</div><div class="code_line">&nbsp;&nbsp; &nbsp;typedef const char&amp; const_reference;</div><div class="code_line">};</div></ol></div></div></div></div><br>
Тогда осталось только создать нужный динамический массив:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">vector&#60;char, char_elem_traits&#62; vec;</div><div class="code_line">// тогда:</div><div class="code_line">// arg_type &nbsp;= char&amp; (по ссылке, но не по константной)</div><div class="code_line">// reference = char&amp;</div><div class="code_line">// const_reference = const char&amp;</div></ol></div></div></div></div><br>
Но заметим, что класс(структура) char_elem_traits переопределяет только один тип - arg_type, а остальные остаются неимзенными по отношению к elem_traits&lt;char&gt;. То есть мы произвели лишнюю работу, определив самостоятельно типы reference и const_reference. Хорошо еще, что тут немного типов, а представьте, что их было бы около 20? 50? Чтобы каждый раз не переписывать общие свойства, можно воспользоваться открытым наследованием и переопределить нужные нам типы:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">class char_elem_traits : public elem_traits&#60;char&#62; {</div><div class="code_line">&nbsp;public:</div><div class="code_line">&nbsp;&nbsp;typedef char&amp; arg_type; // определили тип, который передает по ссылке типы char</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// типы reference и const_reference наследуются</div><div class="code_line">};</div></ol></div></div></div></div><br>
Теперь можно использовать наш класс свойств char_elem_traits точно так же, как мы делали это раньше.<br>
<br>
До этого мы рассматривали только свойства, определяющие необходимые типы. Еще могут быть свойства-значения: они предоставляют нужные константы для данного типа.<br>
Рассмотрим пример: нам надо написать шаблон класса, которому для каждого параметра шаблона(типа) требуются связанные с ним константы. Первая мысль будет такой(пример немного перефразирован из вопроса с форума):<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">template &#60;typename T,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;std::size_t T2 = sizeof(T) * 4,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;std::size_t T3 = sizeof(T) * 2,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;std::size_t T4 = sizeof(T)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// ...</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#62;</div><div class="code_line">class X {</div><div class="code_line">&nbsp;&nbsp;// используем нужные константы</div><div class="code_line">&nbsp;&nbsp;// T2 == sizeof(T) * 4</div><div class="code_line">&nbsp;&nbsp;// T4 == sizeof(T)</div><div class="code_line">};</div></ol></div></div></div></div><br>
Но мы теперь люди продвинутые и знаем, как избежать такого большого количества аргументов шаблона - обернуть все в traits:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">template &#60;typename T&#62;</div><div class="code_line">struct x_traits {</div><div class="code_line">&nbsp;static std::size_t T2 = sizeof(T) * 4;</div><div class="code_line">&nbsp;static std::size_t T3 = sizeof(T) * 2;</div><div class="code_line">&nbsp;static std::size_t T4 = sizeof(T);</div><div class="code_line">};</div><div class="code_line">&nbsp;</div><div class="code_line">template &#60;typename T, typename traits = x_traits&#60;T&#62; &#62;</div><div class="code_line">class X {</div><div class="code_line">&nbsp;&nbsp;// используем нужные константы через traits:</div><div class="code_line">&nbsp;&nbsp;// traits::T2 == sizeof(T) * 4</div><div class="code_line">&nbsp;&nbsp;// traits::T4 == sizeof(T)</div><div class="code_line">};</div></ol></div></div></div></div><br>
Но теперь в нашем коде возникает проблема: если вдруг получится так, что пользователь нашего класса захочет взять адрес нашей константы, компилятор должен будет создать реальную константу в памяти, адрес которой можно взять. Для этого был предуман трюк с enum&#39;ом:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">template &#60;typename T&#62;</div><div class="code_line">struct x_traits {</div><div class="code_line">&nbsp;enum { T2 = sizeof(T) * 4 };</div><div class="code_line">&nbsp;enum { T3 = sizeof(T) * 2 };</div><div class="code_line">&nbsp;enum { T4 = sizeof(T) &nbsp; &nbsp; &nbsp;};</div><div class="code_line">};</div><div class="code_line">&nbsp;</div><div class="code_line">template &#60;typename T, typename traits = x_traits&#60;T&#62; &#62;</div><div class="code_line">class X {</div><div class="code_line">&nbsp;&nbsp;// используем нужные константы через traits:</div><div class="code_line">&nbsp;&nbsp;// traits::T2 == sizeof(T) * 4</div><div class="code_line">&nbsp;&nbsp;// traits::T4 == sizeof(T)</div><div class="code_line">};</div></ol></div></div></div></div><br>
Дело в том, что компилятор не позволяет взять адрес enum-констант. Так что мы теперь точно знаем, что наша константа будет вставлена в код числом.<br>
На данном этапе все хорошо. Но вдруг нам надо доработать класс так, что нужна константа вещественного типа. Но возникает такая проблема: в классах можно инициализировать только статические <strong class='tag-b'>интегральные</strong> константы. В enum&#39;ах тоже можно использовать только целые типы. Что же тогда делать? Остается только определить inline-фунцию, которая бы возвращала нужное значение:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">template &#60;typename T&#62;</div><div class="code_line">struct x_traits {</div><div class="code_line">&nbsp;static std::size_t T2() {</div><div class="code_line">&nbsp;&nbsp;return(sizeof(T) * 4);</div><div class="code_line">&nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;static std::size_t T3() {</div><div class="code_line">&nbsp;&nbsp;return(sizeof(T) * 2);</div><div class="code_line">&nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;static std::size_t T4() {</div><div class="code_line">&nbsp;&nbsp;return(sizeof(T));</div><div class="code_line">&nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;// возвращаемое значение типа double</div><div class="code_line">&nbsp;static double T5() {</div><div class="code_line">&nbsp;&nbsp;return(sizeof(T) * 5 / 7);</div><div class="code_line">&nbsp;}</div><div class="code_line">};</div><div class="code_line">&nbsp;</div><div class="code_line">template &#60;typename T, typename traits = x_traits&#60;T&#62; &#62;</div><div class="code_line">class X {</div><div class="code_line">&nbsp;&nbsp;// используем нужные константы через traits:</div><div class="code_line">&nbsp;&nbsp;// T2: traits::T2() - возвращает тип std::size_t, можно и через enum</div><div class="code_line">&nbsp;&nbsp;// T5: traits::T5() - возвращает тип double, по-другому не сделать, только функция</div><div class="code_line">};</div></ol></div></div></div></div><br>
Надо заметить, что наличие функции на производительность не влияет, так как современные компиляторы способны подставить нужное значение прямо в код вместо вызова функции. Также можно сочетать наличие функций, возвращающих нужные значения вещественного типа, и простые интегральные константы, полученные с помощью enum.<br>
<br>
Теперь мы знаем основные принципы для работы с traits. Так что давайте рассмотрим пример, который помогает расширить стандартную библиотеку C++.<br>
Давайте рассмотрим такую задачу(перефразировано из вопроса с форума):<br>
<div class='tag-quote'><span class='tag-quote-prefix'>Цитата</span> <div class='quote '>Я хочу определить размер файла с помощь класса ifstream. Сам файл весит больше 5 Гб. Функция tellg() возвращает какое-то нереальное значение. Как можно правильно определить размер файла?</div></div><br>
На данный момент все известные мне версии стандартной библиотеки C++ представляют позицию в файле 32-разрядным целым. Но дело в том, что обычные 32-разрядные целые числа не могут представлять размер файла, большего 4 ГБ(происходит переполнение). То есть нам надо каким-либо образом заставить стандартную библиотеку использовать не 32-разрядные числа, а, например 64-разрядные(или вообще наш собственный тип(класс), который мы опишем). Как это сделать? Как вы уже догадались, помогут нам traits.<br>
Как известно, ifstream - это только typedef от класса basic_ifstream. Сам же класс basic_ifstream принимает 2 параметра шаблона: первый из них определяет тип символа, а второй определяет свойста(traits). Так вот эти свойста и должны определять, каким типом представлять позицию в файле, как сравнивать символы и тд. Второй параметр шаблона класса basic_ifstream по умолчанию будет классом char_traits. Это стандартный класс, который описывает основные свойста: нужные типы, как сравнивать символы, присваивать и тд.. Так как мы не собираемся переопределять это <strong class='tag-b'>все</strong>(нам надо заменить только 2 типа), тогда хорошей идеей будет унаследоваться от класса char_traits.<br>
У класса char_traits есть 2 интересующих нас типа(полный список типов можно найти в документации):<br>
1) pos_type - тип, используемый для представления позиции в потоке<br>
2) off_type - тип, используемый для представления смещений между позициями в потоке<br>
Вот их-то как раз нам и надо переопределить. Давайте сделаем первую попытку:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">template &#60;typename char_t&#62;</div><div class="code_line">struct long_pointer_traits : public std::char_traits&#60;char_t&#62; {</div><div class="code_line">&nbsp;typedef __int64 pos_type;</div><div class="code_line">&nbsp;typedef __int64 off_type;</div><div class="code_line">};</div><div class="code_line">&nbsp;</div><div class="code_line">typedef std::basic_ifstream&#60;char, long_pointer_traits&#60;char&#62; &#62; long_ifstream;</div><div class="code_line">&nbsp;</div><div class="code_line">// используем long_ifstream</div></ol></div></div></div></div><br>
Но вот незадача: этот код не компилируется. Дело в том, что pos_type должен уметь конструироваться из нескольких заранее определенных типов(как показало исследование, 2). Базовые типы этого делать не умеют, так что придется написать свой собственный класс. Я не буду заострять внимание на этом классе, так как статья немного не на эту тему. Я просто приведу реализацию этого класса, а если у вас будут какие-то вопросы, то писать либо здесь, либо в PM. Итак, вот код:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">// пространство имен, в которое заносятся детали реализации</div><div class="code_line">namespace detail {</div><div class="code_line">&nbsp;template &#60;typename num_type, typename state_type = std::mbstate_t&#62;</div><div class="code_line">&nbsp;class pos_type_t {</div><div class="code_line">&nbsp;&nbsp; &nbsp; typedef pos_type_t&#60;num_type, state_type&#62; my_type;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; num_type &nbsp; &nbsp;m_pos;</div><div class="code_line">&nbsp;&nbsp; &nbsp; state_type &nbsp;m_state;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; static state_type initial_state;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;public:</div><div class="code_line">&nbsp;&nbsp; &nbsp;// конструкторы</div><div class="code_line">&nbsp;&nbsp; &nbsp; pos_type_t(std::streampos off) : m_pos(off), m_state(initial_state) {}</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;pos_type_t(num_type off = 0) : m_pos(off), m_state(initial_state) {}</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;pos_type_t(state_type state, num_type pos) : m_pos(pos), m_state(state) {}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;// получение состояния потока</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;state_type state() const {</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return(m_state);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;// установка состояния потока</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;void state(state_type st) {</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;m_state = st;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;// получение позиции</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;num_type seekpos() const &nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;return(m_pos);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;// оператор преобразования</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;operator num_type() const {</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;return(m_pos);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;// далее идут операторы, которые осуществляют арифметические операции</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;num_type operator- (const my_type&amp; rhs) const {</div><div class="code_line">&nbsp;&nbsp; &nbsp;return(static_cast&#60;num_type&#62;(*this) - static_cast&#60;num_type&#62;(rhs));</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;my_type&amp; operator+= (num_type pos) {</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;m_pos += pos;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return(*this);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;my_type&amp; operator-= (num_type pos) {</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;m_pos -= pos;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return(*this);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;my_type operator+ (num_type pos) const {</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;my_type tmp(*this);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return(tmp += pos);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;my_type operator- (num_type pos) const {</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;my_type tmp(*this);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return(tmp -= pos);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;// операторы сравнения</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;bool operator== (const my_type&amp; rhs) const {</div><div class="code_line">&nbsp;&nbsp; &nbsp;return(static_cast&#60;num_type&#62;(*this) == static_cast&#60;num_type&#62;(rhs));</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;bool operator!= (const my_type&amp; rhs) const {</div><div class="code_line">&nbsp;&nbsp; &nbsp;return(!(*this == rhs));</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;};</div><div class="code_line">//---------------------------------------------------</div><div class="code_line">&nbsp;// статическая константа, которая обозначает начальное состояние</div><div class="code_line">&nbsp;template &#60;typename num_type, typename state_type&#62;</div><div class="code_line">&nbsp;state_type pos_type_t&#60;num_type, state_type&#62;::initial_state;</div><div class="code_line">}</div><div class="code_line">//---------------------------------------------------</div><div class="code_line">// наконец-то наш класс свойств:</div><div class="code_line">template &#60;typename char_t, typename long_pos_t&#62;</div><div class="code_line">struct long_pointer_traits : public std::char_traits&#60;char_t&#62; {</div><div class="code_line">&nbsp;// определение pos_type через наш только что написанный класс</div><div class="code_line">&nbsp;typedef detail::pos_type_t&#60;long_pos_t&#62; pos_type;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;// определение off_type через тип, переданный во 2 аргументе шаблона</div><div class="code_line">&nbsp;typedef long_pos_t off_type;</div><div class="code_line">};</div><div class="code_line">//---------------------------------------------------</div><div class="code_line">// вводим тип &quot;длинного&quot; файла</div><div class="code_line">typedef std::basic_ifstream&#60;char, long_pointer_traits&#60;char, __int64&#62; &#62; long_ifstream;</div><div class="code_line">&nbsp;</div><div class="code_line">// используем long_ifstream для получения размера файла</div></ol></div></div></div></div><br>
ОК, теперь все компилируется и работает. Но кроме получения позиции в файле, нам обычно надо работать еще с этими файлами(читать, писать). И, конечно, нам приходится работать со строками. Тогда если мы попытаемся считать строку из файла таким образом:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">long_ifstream infile(strFileName, std::ios::binary);</div><div class="code_line">std::string res;</div><div class="code_line">std::getline(infile, res);</div></ol></div></div></div></div><br>
То мы получим ошибку компиляции. Проблема в том, что std::string - это &quot;всего лишь&quot; typedef от std::basic_string. Этот класс принимает 2 параметра шаблона: первый - тип для представления символа, а второй(как вы уже, наверное, догадались) - traits. Так вот, для корректной работы нам надо определить и свой тип строки:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">// &quot;длинные&quot; типы:</div><div class="code_line">typedef std::basic_ifstream&#60;char, long_pointer_traits&#60;char, __int64&#62; &#62; &nbsp;long_ifstream;</div><div class="code_line">typedef std::basic_string&#60;char, long_pointer_traits&#60;char, __int64&#62; &#62; &nbsp; &nbsp;long_string;</div><div class="code_line">&nbsp;</div><div class="code_line">long_ifstream infile(strFileName, std::ios::binary);</div><div class="code_line">long_string res;</div><div class="code_line">std::getline(infile, res);</div></ol></div></div></div></div><br>
Теперь все работает прекрасно. Таким образом, для правильного взаимодействия компонентов стандартной библиотеки нам придется определять нужные типы и работать с ними. К сожалению, на данный момент я не знаю способа, как можно было бы создать нужный тип для стандартных потоков ввода/вывода(cin, cout, cerr, clog). Так что чтобы вывести такую &quot;длинную&quot; строку на экран, надо будет написать свой оператор вывода такой строки. Другого решения мне неизвестно(если кто-то знает - поделитесь, буду признателен).<br>
Также хочу сказать несколько слов о совместимости и переносимости: приведенный мной код по определению размера большого файла был проверен на компиляторах VC7.1 и Intel C++ 8.0. Использовалась стандартная библиотека, которая идет по умолчанию с VC. При работе с ней замечено никаких ошибок не было. Проверялся код и с использованием STLPort версий 4.6.2 и 5.0. Компилировался он без проблем, но работал неправильно. Надеюсь, в дальнейших версиях STLPort&#39;а это будет исправлено и работать будет корректно, так как данный код соответствует стандарту.<br>
<br>
Ну вот, вроде бы и все, что я хотел сообщить по поводу свойств. Надеюсь, данная статья помогла вам разобраться, что это такое и зачем оно надо. Также жду ваши отзывы, комментарии и критику.<br>
<br>
<strong class='tag-b'><span class='tag-size' data-value='12' style='font-size:12pt;'>Использованная литература:</span></strong><br>
* Джосатис, Вандервурд &quot;Шаблоны C++&quot;.<br>
* Николай Джосатис, &quot;Стандартная библиотека С++&quot;.<br>
Собственно, советую почитать эти книги. Насколько мне известно, Герб Саттер и Андрей Александреску писали в своих книгах про свойства, но, к сожалению, мне еще не довелось читать их книги.]]></description>
        <author>byte</author>
        <category>C/C++ FAQ</category>
      </item>
	
      </channel>
      </rss>
	