Использование анонимных пространств имен в файлах заголовков
Кто-то сегодня заявил, что вы никогда не должны использовать анонимные пространства имен в файлах заголовков. Обычно это правильно, но я, кажется, помню, как только кто-то сказал мне, что одна из стандартных библиотек использует анонимные пространства имен в заголовочных файлах для выполнения какой-то инициализации.
Я правильно помню? Может кто-нибудь заполнить детали?
Ответы
Ответ 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
и т.д.).