Итак, я работаю над этой библиотекой (только заголовок), которая имеет несколько модулей и использует встроенное пространство имен для управления версиями. Таким образом, полностью определенные имена могут иногда становиться немного длиннее. Я хотел бы использовать «using namespace x» в качестве детали реализации внутри (встроенных) детальных пространств имен, но это загрязняет внешнее пространство имен.
См. Пример кода на godbolt: https://godbolt.org/z/pdSXrs
Я нашел два обходных пути (см. Ссылку на Godbolt), которые делают то, что я хочу, но кажутся слишком сложными. Есть ли более простой способ сделать это? Должен ли я просто ввести все полные имена (и сохранить сообщения об ошибках в чистоте)? Я хотел бы знать, каковы лучшие практики для «более сложных» конструкций пространства имен.
Изменить: добавлен код, как предложено
// think of these as in header files
namespace mylib{
namespace module0{
inline namespace mystuff{
// this constant conceptually belongs to module 0 but might be used as an
// implementation detail in other modules
int myconst = 42;
}
}
}
namespace mylib{
namespace module1{
// I would like to use this, but pollutes mylib::module1 namespace
inline namespace detail1{
using namespace mylib::module0::mystuff;
struct foo1{
int operator()(){
return myconst;
}
};
}
}
}
namespace mylib{
namespace module2{
inline namespace detail1{
// this works but seems overly complicated
namespace more_detail{
using namespace mylib::module0::mystuff;
struct foo2{
int operator()(){return myconst;}
};
}
// might be very cumbersome to use if lots of classes
using more_detail::foo2;
}
}
}
namespace mylib{
namespace module3{
inline namespace detail1{
// is this a good way to namespace a library...?
namespace more_detail{
using namespace mylib::module0::mystuff;
// not enough namespaces yet?!
namespace devil_of_details{
struct foo3{
int operator()(){return myconst;}
};
}
}
// useable for lots of classes/types in that namespace... but really?!
using namespace more_detail::devil_of_details;
}
}
}
// think of this as myprogram.cpp including the headers
#include <iostream>
int main(){
// polluted namespace. I can probably live with it, but it's not ideal
// constant should only be visible in module0
int x1 = mylib::module1::myconst;
std::cout << x1 << std::endl;
// ok
int x0 = mylib::module0::myconst;
// this is what I ideally want, i.e. not polluting module2 namespace
int x2_error = mylib::module2::myconst;
// this is what I ideally want, i.e. not polluting module3 namespace
int x3_error = mylib::module3::myconst;
// normal usage in cpp file
using namespace mylib::module2;
int x2 = foo2{}();
std::cout << x2 << std::endl;
// ok
using namespace mylib::module0;
std::cout << myconst << std::endl;
}