2008-12-10 19 views
34

Ktoś potwierdził dziś na SO, że nie powinno się nigdy używać anonimowych przestrzeni nazw w plikach nagłówkowych. Zwykle jest to poprawne, ale wydaje mi się, że pamiętam, gdy ktoś powiedział mi, że jedna ze standardowych bibliotek używa anonimowych przestrzeni nazw w plikach nagłówkowych do przeprowadzenia jakiejś inicjalizacji.Zastosowania dla anonimowych przestrzeni nazw w plikach nagłówków

Czy dobrze pamiętam? Czy ktoś może podać szczegóły?

+1

Zobacz tę dyskusję: [http://stackoverflow.com/questions/357404/anonynous-namespaces](http://stackoverflow.com/questions/357404/anonynous-namespaces) –

+0

to wątek skąd ma te informacje z anonimowych przestrzeni nazw w nagłówkach jest zły –

+0

Nie mogę znaleźć niczego w tym wątku o używaniu go w plikach nagłówkowych. Czy ktoś może wyjaśnić, dlaczego tak się nie stało? I czy nadal ma zastosowanie w C++ 11? – baruch

Odpowiedz

20

Jedyna sytuacja, w której bezimienny nazw w nagłówku może być przydatna jest, gdy chcesz rozpowszechniać kod jak tylko plików nagłówkowych. Na przykład duży samodzielny podzbiór Boost to czysto nagłówki.

Token wymieniony w innej odpowiedzi to jeden z przykładów, zastępcze elementy wiążące itp. Wiążą się z innymi.

+0

Myślę, że zrobiłeś z tym dobry punkt. –

+0

Nie należy używać do tego anonimowego obszaru nazw, ponieważ wszystkie one są zwinięte razem w końcowej jednostce kompilacji, co potencjalnie prowadzi do konfliktów przestrzeni nazw. Zamiast tego użyj nazwy, która zgodnie z konwencją oznacza, że ​​zawartość to szczegóły implementacji. Na przykład funkcja boost używa "detail". – thehouse

+0

@thehouse Wydaje się, że źle zrozumiałeś, w jaki sposób Boost używa anonimowych przestrzeni nazw. 'ignore' i' _1', '_2' itd. są symbolami publicznymi - nie należą do' detail'. Zgadzam się jednak, że szczegółowy obszar nazw jest prawidłowym wyborem dla odpowiednika anonimowej przestrzeni nazw w bibliotece nagłówków. –

2

Naprawdę nie widzę żadnej pozytywnej korzyści z używania anonimowych przestrzeni nazw w nagłówkach. Zamieszanie, które może wynikać z posiadania tej samej deklaracji symbolu, oznacza w zasadzie inną rzecz w jednostkach kompilacji, które zawierają ten nagłówek, jest gwarantowanym sposobem przedwczesnego i bolesnego łysienia.

0

Jeśli jest to inicjalizacja, prawdopodobnie byłby to nagłówek iostream (np. istream, ios itd.).

13

Nie widzę sensu umieszczania anonimowego obszaru nazw w pliku nagłówkowym. Mam grepped średnia i nagłówki libstdC++, nie znaleziono anonimowych nazw oprócz jednego w nagłówku tuple (C++ 1x rzeczy):

// 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 

Jest więc można zrobić

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

elementy some_tuple są przypisane zmiennym po lewej stronie (patrz here), podobną technikę stosuje się do iteratora this. Drugi element jest ignorowany.

Ale jak to mówią, należy umieścić go w pliku .cpp, a jedno wystąpienie powinno być udostępnione wszystkim użytkownikom. Oni umieścić oświadczenie o nim w nagłówku jak to wówczas:

extern _Swallow_assign ignore; 
+0

C++ 1x? Przegapiłem coś? –

+0

next C++ version –

+0

Sutter wciąż nazywa to C++ 0x (http://herbsutter.wordpress.com/2008/10/28/september-2008-iso-c-standards-meeting-the-draft-has-landed i nowy konwerter /). –

4

Widziałem, jak dawał domyślną wartość zmiennej w różnych jednostkach tłumaczeniowych. Ale może to spowodować nieoczekiwane zachowanie w przypadku konfliktów nazw.

Przykład

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 

np.CPP

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