Пожалуйста, рассмотрите этот код:
#include <iostream>
namespace Foo{
void ool() // Version A
{
std::cout << "Foo::ool" << std::endl;
}
inline namespace Bar{
void ool() // Version B
{
std::cout << "Foo::Bar::ool" << std::endl;
}
}
}int main()
{
Foo::ool(); // <- error
}
И Clang, и G ++ правильно помечают Foo::ool
как неоднозначно. я могу позвонить Foo::Bar::ool
без проблем, но есть ли способ вызвать версию A без изменения ее декларации?
Я нашел людей в подобном положении, пытающихся понять, что происходит, но я не видел решения для этого случая.
Я нахожусь в этой ситуации, потому что у меня есть проект, который включает в себя декларацию std::__1::pair
а также std::pair
, сделанные в разных местах, с std::__1
будучи встроенным пространством имен. Мне нужен код, чтобы указать на std::pair
в явном виде. Есть ли решение для этого?
Я не думаю, что это возможно; от cppreference:
Квалифицированный поиск имени, который проверяет вмещающее пространство имен, будет включать имена из встроенных пространств имен, даже если то же имя присутствует во вмещающем пространстве имен.
Однако, похоже, что вы не находитесь в описываемой вами ситуации, поскольку вы говорите, что два определения взяты из разных файлов. Таким образом, вы «добавляете в закладки» более внешнее определение, чтобы иметь возможность вызывать его, когда вам это нужно:
#include <iostream>
// Equivalent of first include
namespace Foo{
void ool() // Version A
{
std::cout << "Foo::ool" << std::endl;
}
}
const auto& foo_ool = Foo::ool;
// Equivalent of second include
namespace Foo{
inline namespace Bar{
void ool() // Version B
{
std::cout << "Foo::Bar::ool" << std::endl;
}
}
}
int main()
{
foo_ool(); // Works
}
Если вещь, которую вы хотите добавить в закладки, является типом, то using
Директива должна быть достаточной. Эквивалентный код для вас будет выглядеть так:
#include <my_first_include>
// bookmark code
#include <my_second_include>
// rest of the code
Вы не можете однозначно обратиться к символу, определенному во вложенном пространстве имен, как только будет замечено встроенное пространство имен.
В частности, для вас, квалифицированный поиск в main
справедливо помечен как неоднозначный (как вы сами сказали). Смотрите последний пункт на cppreference:
Квалифицированный поиск имени, который проверяет вмещающее пространство имен, будет включать имена из встроенных пространств имен, даже если то же имя присутствует во вмещающем пространстве имен.
Тем не менее, другие отметили в комментариях, вы, вероятно, сталкиваетесь с проблемой конфигурации при вызове вашей цепочки инструментов когда вы пытаетесь использовать std::pair
,
Чтобы решить вашу проблему, вам нужно убедиться, что компилятор вызывается для компиляции кода C ++ 11, который будет с флагом:
-std=c++11
или же -std=c++0x
в зависимости от вашей версии Clang / GCC
Чтобы дать дополнительный контекст:
Встроенное пространство имен — это функция C ++ 11, в основном введенная для управление версиями символов в библиотеках. Реализация стандартной библиотеки C ++ может затем определять разные версии символов во вложенных пространствах имен (с нестандартными именами), и в зависимости от запрошенной версии библиотеки при компиляции цепочка инструментов определяет одно из этих вложенных пространств имен как встроенное. Похоже, вы используете версию библиотеки c ++ 11 (поскольку она определяет некоторые символы, в частности, pair
во встроенном пространстве имен _1
), поэтому наличие символов во встроенном пространстве имен на самом деле то, что вы хотите.
Я не думаю, что вы можете сослаться ool
неоднозначно, когда встроенное пространство имен имеет метод с тем же именем ool
,
Но Вы можете попробовать это;
#include <iostream>
namespace Foo{
inline namespace A {
void ool() // Version A
{
std::cout << "Foo::ool" << std::endl;
}
}
namespace Bar{
void ool() // Version B
{
std::cout << "Foo::Bar::ool" << std::endl;
}
}
}int main()
{
Foo::ool(); // no error
}
namespace Foo
в namespace A
затем inline
namespace A
,Bar
, Теперь, если вы позвоните Foo::ool();
это вызовет inline A::ool()
Bar::ool
может быть вызван Foo::Bar::ool