Столкновение имен между пространством имен библиотеки 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"и укажите пространство имен внутри заголовка (и исходные файлы библиотеки) и повторно скомпилируйте библиотеку с этими объявлениями, чтобы библиотека и ее клиентский код согласовали пространство имен, в котором находится этот код.

Другие вопросы по тегам