Скрытие приватных констант во встроенном заголовке пространства имен - PullRequest
28 голосов
/ 17 января 2010

У меня есть несколько встроенных функций, содержащихся в пространстве имен в заголовочном файле, и в настоящее время я не могу переместить их в файл 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 реализации?

Ответы [ 3 ]

30 голосов
/ 17 января 2010

Вы не можете, анонимные пространства имен работают для единицы перевода, в которой они определены (или включены в ваш случай).
Вы можете переместить их в пространство имен detail, чтобы сообщить пользователю, что они являются внутренними деталями:

namespace foo {
    namespace detail {
        int magic = 42;
    }

    // ... use detail::magic
}
18 голосов
/ 17 января 2010

Как насчет:

namespace Foo {
    class foo_detail {
    private:
        enum {
            BAR = 1234,
        };

        friend void someFunc();
    };

    inline
    void someFunc() {
        // something with foo_detail::BAR
    }
}

Это делает константу недоступной для всех, кроме функций, которые вы помечаете как друзей. Вы можете сделать класс неструктурируемым, сделав конструктор закрытым, чтобы никто не пытался создать экземпляр класса.

3 голосов
/ 17 января 2010

Поместите их в специальное пространство имен или назовите их специально, в сочетании с соглашением проекта о том, что такие вещи не являются общедоступными:

namespace foo {
  namespace detail { // as in "implementation details"
    inline int answer() { return 42; }
    const int perfect = 28;
  }
  std::string _question(); // not part of foo's "public interface" by convention

  int this_is_public() {
    using namespace detail; // now don't have to prefix detail::
    return answer() + perfect + _question().length();
  }
}

Любой, кто использует имена, задокументированные как непубличные, обойдет любую «защиту»Вы пытаетесь;что подчеркивает реальную проблему: документирование того, что является частью общедоступного интерфейса и на которое можно положиться.

Безымянные пространства имен решают другую проблему: получение имен, уникальных для конкретного TU.Они здесь не помогут.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...