Одновременно используя 2 версии boost

Я использую RHEL 5.3, который поставляется с gcc 4.1.2 и boost 1.33. Есть некоторые функции, которые я хочу, которые отсутствуют в boost 1.33. Поэтому мысль заключалась в том, чтобы перейти на новую версию релиза 1.43.

  • Можно ли одновременно использовать некоторые библиотеки заголовков из boost 1.43, а остальные - от 1.33? Например, я хочу использовать unorded_map, который отсутствует в boost 1.33.

  • Можно ли использовать одновременно бинарные библиотеки ускорения из разных выпусков?

Ответы

Ответ 1

НЕТ - никогда не делайте этого!

Это невозможно, вы, вероятно, получите случайные сбои.

Единственный способ сделать это правильно - использовать переименование пространства имен: т.е. создать альтернативу версии, размещенной в разных пространствах имен.

Последняя версия BCP предоставляет эту опцию. Таким образом, вы будете использовать что-то вроде boost_1_43 вместо boost. Но для вас это будет совершенно прозрачно. Но вы все равно должны знать из того, что вы не можете использовать две версии boost в том же файле cpp.

Также рассмотрите эту дискуссию: Создание библиотеки с обратным совместимым ABI, который использует Boost

Любимый script переименовывает пространство имен, определяет и включает, поэтому вы можете фактически включить два версии boost, такие как

#include <boost/foo.hpp>
#include <myboost/bar.hpp>

boost::foo f;
myboost::bar b;

Boost BCP не позволяет этого.

Но все же вы должны быть осторожны, так как некоторые библиотеки экспортируют внешние символы "C" без boost prefix, boost:: thread и boost:: regex C API (regexec, regcomp)

Edit

В качестве примера такой проблемы создайте следующие файлы:

a.cpp:

template<typename Foo>
Foo add(Foo a, Foo b)
{
        return a+b;
}


int foo(int x,int y)
{
        return add(x,y);
}

b.cpp:

template<typename Foo>
Foo add(Foo a, Foo b)
{
        return a-b;
}


int bar(int x,int y)
{
        return add(x,y);
}

test.cpp:

#include <iostream>

int foo(int,int);
int bar(int,int);

int main()
{
        std::cout<< foo(10,20) <<" " <<bar(10,20) << std::endl;
}

Скомпилируйте их:

g++ a.cpp b.cpp test.cpp

Вы ожидаете:

30 -10

Но вы получите

30 30

или

-10 -10

В зависимости от порядка привязки.

Таким образом, используя две форсированные версии, вы можете случайно использовать символы из другого boost и crash то же, что и в этом программном символе int add<int>(int,int), разрешено одному символу если он помещен в разные единицы компиляции.

Ответ 2

С некоторой удачей (и большой заботой) вы, вероятно, можете уйти с использованием совершенно новых заголовков. Для почти любого другого, это может стать уродливым в спешке, потому что некоторые части Boost относятся к другим частям, и если какой-то код v 1.33 случайно загружает заголовок v. 1.43 для его зависимости, есть довольно хороший шанс, что вы собираетесь чтобы получить некоторые проблемы в результате - о лучшем, на что вы можете надеяться, - это быстрая, чистая смерть (сбой) в этот момент, но вы можете легко стать намного хуже (например, размывание данных).

Ответ 3

Обновление

Я думаю, что мой оригинальный ответ делает слишком много предположений о возможностях компоновщика и используемых опциях, и вполне возможно, что это будет совершенно неправильно. Обычно я удаляю его, но есть некоторые моменты в обсуждении, которые не включены в другие ответы.

Я нахожу последствия для того, что нужно для создания хорошо организованной библиотеки с закрытым исходным кодом, просто потрясающей.

Оригинальный ответ

Пока вы используете одну версию на этапе компиляции, вы должны быть в порядке, потому что код генерируется во время компиляции, а сгенерированные символы должны ограничиваться рамкой этапа компиляции.

Я предполагаю, что Boost по-прежнему является библиотекой шаблонов, не имеющей связующих библиотек. Если это не так, вы все равно в порядке, пока вы не связываетесь с более чем одной версией библиотеки.

Возможно, я ошибаюсь, но подразумевается, что вы не можете использовать стороннюю библиотеку, созданную для другой версии Boost, из версии, определенной для вашего приложения. Ничто из того, что я читал или не слышал даже намеков на то, что это ограничение применяется.

Если вы создаете собственное приложение, я бы придерживался одной версии Boost для всего вашего собственного кода. Это не должна быть та же самая версия, которая предоставляется RHEL.

Обновление

В сравнении с примером Artyom сценарий, о котором я говорю, более похож на это:

g++ -c -I/usr/include/boost_1.31 a.cpp
g++ -c -I/usr/include/boost_1.39 b.cpp
ar rcs liba.a a.o
ar rcs libb.a b.o
g++ -I/usr/include/boost_1.41 test.cpp liba.a libb.a -o test

... и теперь я понимаю точку Артема, потому что это зависит от того, предпочитает ли компоновщик символы в одном файле библиотеки или нет.