![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
THE BOOST MPL LIBRARY: Broken Integral Constant ExpressionsBoost , ,
|
Front Page / Technical Details / Portability / Broken Integral Constant Expressions |
Это, пожалуй, самая удивительная из проблем переносимости, которые мы собираемся обсудить, не в последнюю очередь потому, что для многих программистов на C++ их повседневный опыт, кажется, не указывает на какие-либо проблемы в этой области. В конце концов, целочисленные вычисления времени компиляции вдоль линий:
enum flags { flag1 = (1 << 0) , flag2 = (1 << 1) , flag3 = (1 << 2) ... };
оченьраспространены в C++, и вряд ли есть компилятор, который не может справиться с этим правильно. Хотя арифметика сама по себе редко бывает проблематичной, когда вы пытаетесь смешать ее с шаблонами на определенных недостающих компиляторах, возникают всевозможные новые проблемы. К счастью, как и в случае с остальными проблемами переносимости, которые мы обсуждаем здесь, проблема уходит в прошлое по мере выпуска новых версий компилятора. Большинство последних компиляторов многих поставщиков уже свободны от этих проблем.
Проблема на самом деле многогранна; существует ряд различных подвопросов. Некоторые из них присутствуют в одном наборе компиляторов, некоторые в другом, и это не редкость для кода, который работает для одного компилятора, чтобы сломать другой и наоборот. Если это звучит как кошмар для вас, это так! Если вас интересует конкретный список вопросов, пожалуйста, обратитесь к превосходному "Руководство по кодированию для интегральных постоянных выражений" резюме. Для целей нашего обсуждения здесь достаточно сказать, что если ваш код должен работать на одном из компиляторов, перечисленных как проблемные в этой области, вы можете смело предположить, что если вы решите бороться с ними в каждом конкретном случае, скорее всего, вы не сможете поддерживать свое здравомыслие очень долго.
С положительной стороны, когда у вас есть проблема с интегральной арифметикой, диагностика почти всегда проста: обычно сообщение об ошибке отсылает вас к точному месту в коде, которое вызывает проблемы, и суть проблемы очевидна из текста ошибки, или она становится очевидной, как только вы столкнулись с той же ошибкой пару раз. Например, если мы выкинем этот хорошо сформированный фрагмент на MSVC 7.1 (иначе отличный компилятор!)
void value(); // compares two Integral Constants template< typename N1, typename N2 > struct less : bool_< (N1::value < N2::value) > // line #8 { };
Мы получаем:
portability.cpp(8) : warning C4346: 'N2::value' : dependent name is not a type prefix with 'typename' to indicate a type portability.cpp(10) : see reference to class template instantiation 'less<N1,N2>' being compiled portability.cpp(8) : error C2143: syntax error : missing ',' before ')' portability.cpp(9) : error C2143: syntax error : missing ';' before '{' portability.cpp(10) : error C2143: syntax error : missing ';' before '}' portability.cpp(10) : fatal error C1004: unexpected end of file found
Сами по себе ошибки далеко не идеальны, но, по крайней мере, нам указывают на правильную линию и даже правильную часть линии. Выше в основном читается как "что-то не так между скобками ", и что плюс ошибка "syntax " часть обычно достаточно подсказки.
Несмотря на то, что проблемы настолько многочисленны и многогранны, а обходные пути противоречивы, проблемы могут быть надежно скрыты под слоем абстракции библиотеки. Основная идея очень проста: мы всегда можем обернуть константы в типы и передать их. Тогда остается только реализовать алгебраические метафункции, которые работают на таких обертках, один раз, и мы дома в безопасности.
Если вам это кажется знакомым, вероятно, это потому, что вы уже посмотрели на MPL и знаете, что подход, который мы только что описали, на самом делестандартный способ выполнения арифметики в библиотеке. Хотя это мотивировано более общими наблюдениями, этот факт очень удобен для пользователей библиотеки, которые заботятся о переносимости своих численно-тяжелых метапрограмм. Примитивы MPL уже существуют, и, что более важно, они уже реализуют необходимые обходные пути, поэтому ваш цифровой код просто работает. На самом деле, если вы остаетесь в идиомах типа-обертки библиотеки, эти конкретные проблемы никогда не выходят из ее слоя абстракции.
Наконец, есть цена отказа от встроенной арифметики в целом, а именно снижение читаемости и увеличение накладных расходов на компиляцию на некоторых компиляторах. Тем не менее, в большинстве случаев преимущества арифметики на основе типов имеют ее небольшие недостатки.
Статья THE BOOST MPL LIBRARY: Broken Integral Constant Expressions раздела может быть полезна для разработчиков на c++ и boost.
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.
:: Главная :: ::
реклама |