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

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

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

10.12.2008 20:49:11
Смотрите это обсуждение: http://stackoverflow.com/questions/357404/anonynous-namespaces
John D. Cook 10.12.2008 21:09:41
это нить, откуда он получает эту информацию из анонимных пространств имен в заголовках - плохо
Johannes Schaub - litb 10.12.2008 21:11:05
Я не могу найти ничего в этой теме об использовании его в заголовочных файлах. Кто-нибудь может объяснить, почему это не так? И это все еще применяется в C ++ 11?
Baruch 28.08.2014 09:31:53
5 ОТВЕТОВ
РЕШЕНИЕ

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

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

27
11.12.2008 09:46:07
Вы не должны использовать анонимное пространство имен для этого, так как все они свернуты вместе в окончательном модуле компиляции, что может привести к конфликтам пространства имен. Вместо этого используйте имя, которое, по соглашению, означает, что содержимое - это детали реализации. Boost, например, использует detail.
thehouse 24.05.2012 19:26:11
@thehouse Вы, похоже, неправильно поняли, как Boost использует анонимные пространства имен. ignoreи _1, и _2т.д. являются общественными символами - они не принадлежат detail. Но я согласен, что детальное пространство имен обычно является правильным выбором для библиотеки заголовков, эквивалентной анонимному пространству имен.
James Hopkin 30.05.2012 10:36:57
@JamesHopkin Всегда рад учиться. Можете ли вы объяснить, почему _1 и _2 находятся в анонимном пространстве имен, а не просто в namespace boost? Какие преимущества это дает?
thehouse 30.05.2012 14:38:14
@thehouse Это хитрость, позволяющая библиотеке только заголовка предоставлять глобальные объекты, которые обычно вызывают ошибки ссылок. Помещение объекта в анонимное пространство имен заставляет каждый модуль компиляции создавать свой собственный экземпляр. Множественные экземпляры не имеют значения в случае _1, _2 и т. Д., Поскольку они не сохраняют состояние. Другой способ добиться того же эффекта - использовать статический член класса шаблона, но тогда клиент должен будет напечатать что-то вроде Dummy <> :: _ 1, а не просто _1.
James Hopkin 31.05.2012 08:15:45
@JamesHopkin Интересно, спасибо. Ранее я помещал глобальные данные в заголовки, но пользователям не требовался прямой доступ к ним, поэтому я мог использовать статический член (фактически статическую переменную в статическом методе IIRC).
thehouse 31.05.2012 10:55:06

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

2
10.12.2008 21:25:28

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

0
23.12.2009 09:16:25

Я не вижу смысла помещать анонимное пространство имен в заголовочный файл. Я собрал стандартные и заголовки libstdc ++, не нашел анонимных пространств имен кроме одного в tupleзаголовке (C ++ 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;
15
23.05.2017 12:10:15
C ++ 1x? Я что-то пропустил?
Adam Mitz 11.12.2008 04:09:10
Саттер все еще называет его C ++ 0x ( herbutter.wordpress.com/2008/10/28/… ).
Adam Mitz 11.12.2008 13:03:15
подождите .. теперь я понимаю, почему он назвал меня пессимистом :) хорошо, а некоторые другие пессимисты называют это c ++ 1x. давайте посмотрим, кто выиграет ставку: p
Johannes Schaub - litb 11.12.2008 13:32:40
@Johannes: Вы сделали :-)
Cameron 13.03.2012 15:03:59

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

пример

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
7
8.09.2015 08:21:51