HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-03-10
1 <p>Теги: с++, экспорт шаблонов, shared library, dll, std::shared_ptr&lt;someusefulclass&gt;, std::shared_ptr, standart-layout, двойное инстанцирование шаблона, бинарная совместимость</p>
1 <p>Теги: с++, экспорт шаблонов, shared library, dll, std::shared_ptr&lt;someusefulclass&gt;, std::shared_ptr, standart-layout, двойное инстанцирование шаблона, бинарная совместимость</p>
2 <p>Предположим, вам требуется написать разделяемую библиотеку (DLL в терминологии Windows и shared library в мире *nix). Допустим, в библиотеке реализована некоторая фабричная функция, которая создаёт очень полезные для пользователей объекты. Примерно так:</p>
2 <p>Предположим, вам требуется написать разделяемую библиотеку (DLL в терминологии Windows и shared library в мире *nix). Допустим, в библиотеке реализована некоторая фабричная функция, которая создаёт очень полезные для пользователей объекты. Примерно так:</p>
3 #if defined(_MSC_VER) // Microsoft #define EXPORT __declspec(dllexport) #define IMPORT __declspec(dllimport) #elif defined(__GNUC__) // GCC #define EXPORT __attribute__((visibility("default"))) #define IMPORT #else // do nothing and hope for the best? #define EXPORT #define IMPORT #pragma warning Unknown dynamic link import/export semantics. #endif<p>std::shared_ptr&amp;lt;SomeUsefulClass&amp;gt; create();</p>
3 #if defined(_MSC_VER) // Microsoft #define EXPORT __declspec(dllexport) #define IMPORT __declspec(dllimport) #elif defined(__GNUC__) // GCC #define EXPORT __attribute__((visibility("default"))) #define IMPORT #else // do nothing and hope for the best? #define EXPORT #define IMPORT #pragma warning Unknown dynamic link import/export semantics. #endif<p>std::shared_ptr&amp;lt;SomeUsefulClass&amp;gt; create();</p>
4 <p>Если вы действительно написали подобный код, то вы на пороге больших проблем. Вернее, даже не вы, а пользователи библиотеки.</p>
4 <p>Если вы действительно написали подобный код, то вы на пороге больших проблем. Вернее, даже не вы, а пользователи библиотеки.</p>
5 <h2>В чем же проблема?</h2>
5 <h2>В чем же проблема?</h2>
6 <p>Проблема в двойном инстанцировании шаблона<b>std::shared_ptr&lt;SomeUsefulClass&gt;</b>. Первое произойдёт непосредственно при компиляции вашей библиотеки, а второе - в момент компиляции пользовательского кода, который будет использовать библиотеку.</p>
6 <p>Проблема в двойном инстанцировании шаблона<b>std::shared_ptr&lt;SomeUsefulClass&gt;</b>. Первое произойдёт непосредственно при компиляции вашей библиотеки, а второе - в момент компиляции пользовательского кода, который будет использовать библиотеку.</p>
7 <p>А теперь самое главное - никто не может гарантировать, что эти две результирующие версии, казалось бы, одного и того же шаблона будут одинаковыми. Стандарт C++ описывает только интерфейс класса<b>std::shared_ptr</b>, но не детали реализации.</p>
7 <p>А теперь самое главное - никто не может гарантировать, что эти две результирующие версии, казалось бы, одного и того же шаблона будут одинаковыми. Стандарт C++ описывает только интерфейс класса<b>std::shared_ptr</b>, но не детали реализации.</p>
8 <p>Если библиотека и пользовательский код были собраны разными компиляторами (или даже разными версиями одного и того же компилятора), могут возникнуть проблемы. Можно подумать, что основная проблема - недостаточно полная формулировка стандарта в части описания деталей<b>std::shared_ptr</b>. Но это не совсем так.</p>
8 <p>Если библиотека и пользовательский код были собраны разными компиляторами (или даже разными версиями одного и того же компилятора), могут возникнуть проблемы. Можно подумать, что основная проблема - недостаточно полная формулировка стандарта в части описания деталей<b>std::shared_ptr</b>. Но это не совсем так.</p>
9 <p>Ещё одна проблема заключается в том, что бинарная совместимость гарантируется только для<b>standart-layout</b>типов данных. Только такие типы можно без опаски использовать на стыке между кодом, который может быть собран разными компиляторами (или разными версиями).</p>
9 <p>Ещё одна проблема заключается в том, что бинарная совместимость гарантируется только для<b>standart-layout</b>типов данных. Только такие типы можно без опаски использовать на стыке между кодом, который может быть собран разными компиляторами (или разными версиями).</p>
10 <h2>Почему бы стандарту C++ не дать больше гарантий?</h2>
10 <h2>Почему бы стандарту C++ не дать больше гарантий?</h2>
11 <p>Причина всё та же - эффективность. Чем меньше ограничений накладывает стандарт языка, тем больше оптимизаций может выполнить компилятор.</p>
11 <p>Причина всё та же - эффективность. Чем меньше ограничений накладывает стандарт языка, тем больше оптимизаций может выполнить компилятор.</p>
12 <p><b>Что почитать подробнее:</b><a>StandardLayoutType_2</a><a>StandardLayoutType_2</a></p>
12 <p><b>Что почитать подробнее:</b><a>StandardLayoutType_2</a><a>StandardLayoutType_2</a></p>
13 <p><i>Остались вопросы? Пишите в комментариях!</i></p>
13 <p><i>Остались вопросы? Пишите в комментариях!</i></p>
14  
14