Использование анонимных пространств имен в файлах заголовков

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

Я правильно помню? Может кто-нибудь заполнить детали?

Ответ 1

Единственная ситуация, при которой неназванное пространство имен в заголовке может быть полезным, - это когда вы хотите распространять код только в виде файлов заголовков. Например, большое автономное подмножество Boost является чисто заголовком.

Токен ignore для кортежей, упомянутый в другом ответе, является одним из примеров, тэги _1, _2 и т.д. bind являются другими.

Ответ 2

Я не вижу смысла помещать анонимное пространство имен в заголовочный файл. Я grepped стандарт и заголовки libstdС++, не нашел анонимных пространств имен, кроме одного в заголовке tuple (материал С++ 1x):

  // A class (and instance) which can be used in 'tie' when an element
  // of a tuple is not required
  struct _Swallow_assign
  {
    template<class _Tp>
      _Swallow_assign&
      operator=(const _Tp&)
      { return *this; }
  };

  // TODO: Put this in some kind of shared file.
  namespace
  {
    _Swallow_assign ignore;
  }; // anonymous namespace

Это значит, что вы можете сделать

std::tie(a, std::ignore, b) = some_tuple;

элементам some_tuple присваиваются переменные с левой стороны (см. здесь), аналогичный метод используется для этот итератор. Второй элемент игнорируется.

Но, как говорится, он должен быть помещен в файл .cpp, и один экземпляр должен использоваться всеми пользователями. Затем они помещают объявление в заголовок следующим образом:

extern _Swallow_assign ignore;

Ответ 3

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

Пример

a.hpp

namespace
{
    const char name[] = "default";
}
// This macro will hide the anonymous variable "name"
#define SET_NAME(newname) \
static const char name[] = newname;

b.cpp

#include "a.hpp"
SET_NAME("file b") // name is "file b" in this translation unit

c.cpp

#include "a.hpp"
SET_NAME("file c") // name is "file c" in this translation unit

d.cpp

#include "a.hpp"
// name is "default" in this translation unit

e.cpp

#include "a.hpp"
static const char name[] = "unintended";
// accidently hiding anonymous name

Ответ 4

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

Ответ 5

Если это инициализация, вероятно, это заголовок iostream (например, istream, ios и т.д.).