Скрытие частных констант в встроенном заголовке пространства имен
У меня есть некоторые встроенные функции, содержащиеся в пространстве имен в файле заголовка, и я в настоящее время не в состоянии переместить их в файл cpp. Некоторые из этих встроенных функций используют магические константы, например:
// Foo.h
namespace Foo
{
const int BAR = 1234;
inline void someFunc()
{
// Do something with BAR
}
}
Однако, я хочу, чтобы эти магические константы были личными - какие-нибудь идеи? Моя первая мысль заключалась в том, чтобы использовать анонимное пространство имен таким образом:
// Foo.h
namespace Foo
{
namespace
{
// 'private' constants here
const int BAR = 1234;
}
inline void someFunc()
{
// Do something with BAR
}
}
Однако это не работает, и Foo::BAR
доступен для любого файла cpp, который включает Foo.h
? Есть ли способ сделать это без создания файла cpp реализации?
Ответы
Ответ 1
Вы не можете, анонимные пространства имен работают для единицы перевода, в которой они определены (или включены в ваш случай).
Вы могли бы переместить их в пространство имен detail
, чтобы сообщить пользователю, что они являются внутренними данными:
namespace foo {
namespace detail {
int magic = 42;
}
// ... use detail::magic
}
Ответ 2
Как насчет:
namespace Foo {
class foo_detail {
private:
enum {
BAR = 1234,
};
friend void someFunc();
};
inline
void someFunc() {
// something with foo_detail::BAR
}
}
Это делает константу недоступной для кого-либо еще, кроме функций, которые вы отмечаете как друзей. Вы можете сделать класс неконструктивным, сделав его закрытым, чтобы убедиться, что никто не пытается инициализировать класс.
Ответ 3
Поместите их в специальное пространство имен или назовите их специально, в сочетании с соглашением с проектом, что такие вещи не являются общедоступными:
namespace foo {
namespace detail { // as in "implementation details"
inline int answer() { return 42; }
const int perfect = 28;
}
std::string _question(); // not part of foo "public interface" by convention
int this_is_public() {
using namespace detail; // now don't have to prefix detail::
return answer() + perfect + _question().length();
}
}
Любой, кто использует имена, задокументированные как непубличные, будет обходить любую "защиту", которую вы пытаетесь; что подчеркивает реальную проблему: документирование какой части открытого интерфейса и на что можно положиться.
пространства имен имен решают другую проблему: получение имен, уникальных для конкретного ТУ. Они здесь не помогут.