Столкновение имен между пространством имен библиотеки C++ и функцией C linux
Linux <ncurses.h>
заголовок определяет функцию meta
и библиотека метапрограммирования C++ meta
помещает весь свой код в глобальное пространство имен meta
,
Как я могу использовать оба в одной и той же программе C++ (не обязательно один и тот же TU, но это было бы неплохо)? Есть ли способ обойти конфликт имен?
Я могу придумать два хрупких обходных пути, но их легко сломать:
Обходной путь A:
namespace linux { #include <ncurses.h> } // namespace linux using linux::max_align_t; // ncurses assumes it is in the global namespace #include <meta/meta.hpp>
компилируется, но, вероятно, не сможет связать, так как
ncurses
символы ожидаются в глобальном пространстве имен.Обходной путь B:
#include <ncurses.h> namespace cpp { #include <meta/meta.hpp> } // namespace cpp
очень хрупкий, так как он будет работать только до тех пор, пока
meta
библиотека не предполагает, что какой-либо из ее символов находится в глобальном пространстве имен. То есть, если библиотеке необходимо устранить неоднозначность внутреннего символа и использовать::meta::symbol_name
для этого этот подход сломается.
2 ответа
Я хотел бы предложить обходной путь C: изолировать ваш код так, чтобы meta
использование библиотеки и ncurses
использовать в отдельных переводческих единицах в вашем проекте. Таким образом, в любом конкретном модуле перевода нет ни одного символа, используемого в качестве пространства имен и глобальной функции.
Я достаточно уверен, что ни А, ни В не будут работать, по крайней мере, как указано. Вы указали на одного из них, но я думаю, что это менее вероятно из двух. Есть две проблемы, которые в основном являются зеркальным отображением друг друга.
Если код в ncurses
объявлен как extern "C"
(типично для многих библиотек C, которые были созданы для работы с C++), окружение их пространством имен фактически не будет работать - extern "C"
Объявление в основном игнорирует пространства имен и объявляет функцию в глобальном пространстве имен. Пространство имен ничего не изменит, и вы все равно столкнетесь.
Если содержание <ncurses.h>
не объявлено extern "C"
, тогда вы столкнетесь с проблемой, которую вы упомянули: библиотека построена с функциями в глобальном пространстве имен, но клиентский код видит определения для кода в linux
Пространство имен. Поскольку пространство имен влияет на искаженное имя (таким образом, оно предотвращает конфликт), ваш код не сможет связать. Все linux::*
функции будут отображаться как неразрешенные внешние факторы.
Чтобы это работало, вам нужно убедиться, что ни один из библиотечных кодов не объявлен extern "C"
и укажите пространство имен внутри заголовка (и исходные файлы библиотеки) и повторно скомпилируйте библиотеку с этими объявлениями, чтобы библиотека и ее клиентский код согласовали пространство имен, в котором находится этот код.