Объявление альтернативного имени пространства имен C++ и предописание

Я пользуюсь сторонней библиотекой 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. Решение (по крайней мере, в моей ситуации) находится в комментариях к принятому ответу.

9
задан Dave Mateer 14 June 2010 в 13:39
поделиться

4 ответа

Похоже, что для этого есть уродливое обходное решение, но хорошего решения нет.

Для 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 как пространство имен, поэтому, когда компилятор пытается назначить псевдоним позже, он не может быть и тем, и другим, поэтому компилятор жалуется.

4
ответ дан 4 December 2019 в 23:38
поделиться

Э ... То, что вы говорите, мне кажется обратным. Напротив, какой смысл объявлять ваш класс членом пространства имен tplib ? (Забыв на секунду, что это даже не пространство имен, а скорее псевдоним пространства имен, поэтому вы получаете ошибку.)

Очевидно, что у вас есть какая-то система контроля версий, построенная на пространствах имен и пространстве имен псевдонимы. Если ваш класс впервые представлен в какой-то конкретной «версии» пространства имен (например, 44) - это пространство имен, в котором он должен быть объявлен. Почему вы пытаетесь засунуть свое объявление класса «назад во времени», то есть в все прошлые версии пространства имен (например, 43 и, скажем, 30)? Ваш класс не существовал в предыдущих версиях, поэтому вы не должны принудительно использовать его там.

0
ответ дан 4 December 2019 в 23:38
поделиться

РЕДАКТИРОВАТЬ: Я заметил, что упустил суть вопроса - пожалуйста, не обращайте внимания!

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

Пространства имен существуют для предотвращения конфликтов конфликтующих символов (классов, определений типов, перечислений и т. Д.), Помещая их в их собственное пространство имен, тем самым создавая уникальный полностью определенный символ из потенциально идентичных частично определенных. Добавление собственного кода в пространство имен третьей стороны может вызвать проблемы, если (например) в более поздней версии они решат, что тоже хотят использовать тот же символ (например, добавив свой собственный SomeClassInTpLib ) - внезапно Конфликты именования пространств имен предназначены для предотвращения их уродливой головы. Вот почему обычно не рекомендуется добавлять в пространство имен std .

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

0
ответ дан 4 December 2019 в 23:38
поделиться

Я думаю, ваша проблема связана с тем, что 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();
}
2
ответ дан 4 December 2019 в 23:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: