Я пользуюсь сторонней библиотекой C++, которая помещает все ее классы в имеющем версию пространстве имен, давайте назовем его tplib_v44
. Они также определяют универсальный псевдоним пространства имен:
namespace tplib = tplib_v44;
Если вперед - объявляют члена библиотеки в моем собственном.h файле с помощью универсального пространства имен...
namespace tplib { class SomeClassInTpLib; }
... Я получаю ошибки компилятора на заголовке в сторонней библиотеке (который включается позже в моем .cpp файле реализации):
error C2386: 'tplib' : a symbol with this name already exists in the current scope
Если я использую определенное для версии пространство имен, то все хорошо работает, но затем... какой смысл? Что лучший способ состоит в том, чтобы иметь дело с этим?
[РЕДАКТИРОВАНИЕ] к вашему сведению для будущих средств просмотра, это было библиотекой ICU. Решение (по крайней мере, в моей ситуации) находится в комментариях к принятому ответу.
Похоже, что для этого есть уродливое обходное решение, но хорошего решения нет.
Для ACE (с приличным объяснением) и Xerces (с язвительным комментарием "так работает c++"), они определяют макросы, которые можно использовать, чтобы сделать это "обобщенно".
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
class ACE_Reactor;
ACE_END_VERSIONED_NAMESPACE_DECL
XERCES_CPP_NAMESPACE_BEGIN
class DOMDocument;
class DOMElement;
XERCES_CPP_NAMESPACE_END
Это похоже на неудачный артефакт c++, попробуйте поискать эти макросы в вашем tplib
.
Стандарт рассматривает пространства имен и псевдонимы пространств имен как разные вещи. Вы объявляете tplib
как пространство имен, поэтому, когда компилятор пытается назначить псевдоним позже, он не может быть и тем, и другим, поэтому компилятор жалуется.
Э ... То, что вы говорите, мне кажется обратным. Напротив, какой смысл объявлять ваш класс членом пространства имен tplib
? (Забыв на секунду, что это даже не пространство имен, а скорее псевдоним пространства имен, поэтому вы получаете ошибку.)
Очевидно, что у вас есть какая-то система контроля версий, построенная на пространствах имен и пространстве имен псевдонимы. Если ваш класс впервые представлен в какой-то конкретной «версии» пространства имен (например, 44) - это пространство имен, в котором он должен быть объявлен. Почему вы пытаетесь засунуть свое объявление класса «назад во времени», то есть в все прошлые версии пространства имен (например, 43 и, скажем, 30)? Ваш класс не существовал в предыдущих версиях, поэтому вы не должны принудительно использовать его там.
РЕДАКТИРОВАТЬ: Я заметил, что упустил суть вопроса - пожалуйста, не обращайте внимания!
Помимо проблем, выделенных в других ответах, меня также немного беспокоит то, что вы пытаетесь добавить свой собственный код в пространство имен, определенное третьей стороной.
Пространства имен существуют для предотвращения конфликтов конфликтующих символов (классов, определений типов, перечислений и т. Д.), Помещая их в их собственное пространство имен, тем самым создавая уникальный полностью определенный символ из потенциально идентичных частично определенных. Добавление собственного кода в пространство имен третьей стороны может вызвать проблемы, если (например) в более поздней версии они решат, что тоже хотят использовать тот же символ (например, добавив свой собственный SomeClassInTpLib
) - внезапно Конфликты именования пространств имен предназначены для предотвращения их уродливой головы. Вот почему обычно не рекомендуется добавлять в пространство имен std
.
Гораздо более безопасное решение, позволяющее полностью избежать этой проблемы, - просто использовать ваше собственное пространство имен.Назовите его tplib_ex
или что-то подобное, и связь по-прежнему будет ясна, но конфликт не будет проблемой, и ваша проблема, связанная с псевдонимом, также исчезнет.
Я думаю, ваша проблема связана с тем, что tplib является псевдонимом, а не реальным пространством имен
Поскольку управление версиями находится внутри сторонней библиотеки, вы, возможно, не сможете его использовать, но с помощью версионное пространство имен внутри неверсированного пространства имен (а не псевдоним), похоже, работает для g ++ 4.0.1 и 4.1.2. Однако у меня такое чувство, что это не должно работать ... и, возможно, есть некоторые другие проблемы, о которых я не знаю.
//This is the versioned namespace
namespace tplib_v44
{
int foo(){ return 1; }
}
//An unversioned namespace using the versioned one
namespace tplib
{
using namespace tplib_v44;
}
//Since unversioned is a real namespace, not an alias you can add to it normallly.
namespace tplib
{
class Something {};
}
int main()
{
//Just to make sure it all works as expected
tplib::foo();
}