2009-09-04 16 views
6

Mam ten poważny problem. Mam wyliczenie zasięgu 2 nazw takiego:Konflikt między przestrzenią nazw a zdefiniuj

namespace FANLib { 
namespace ERROR { 

    enum TYPE { 

     /// FSL error codes 
     FSL_PARSER_FILE_IERROR,... 

i gdzieś w moim kodu, używam go tak:

FANLib::Log::internalLog(FSLParser::FILE_IERROR, file_ierror, true, FANLib::ERROR::FSL_PARSER_FILE_IERROR); 

Wszystko kompiluje dobrze i dobrze, ale jeśli zdarza mi się to " windows.h ", dostaję błędy! Problem jest w „WinGDI.h”, która ma tę linię:

#define ERROR    0 

i sprawia, że ​​kompilator myśleć, że po FANLib :: ..., jest zerem! Błąd pojawia się:

Error 1 error C2589: 'stała': nielegalne znak po prawej stronie '::'

Błąd 2 error C2059: błąd składni: '::'

błąd 3 error C2039: „FSL_PARSER_FILE_IERROR”: nie jest członkiem globalnej przestrzeni nazw „`””

Czy mogę coś z tym zrobić, bez konieczności zmiany nazw ze względu na moje jakiegoś bezmyślnego #define? Czytałem w innym poście, że mogłem #undef ERROR, ale jak bezpieczne jest to?

Odpowiedz

14

Zasadniczo należy unikać używania identyfikatorów uniwersalnych, ponieważ są one używane w makrach. W tym przypadku zmieniłbym nazwę przestrzeni nazw.

(Na marginesie, <windows.h>#define S inne rzeczy jak GetPrinter i rzeczywiście robi się denerwujące. I zwykle z #undef wtedy. Pomaga również zawierać tylko <windows.h> w plikach .cpp i upewnij się, że zakres dotknięte nagłówku jest tak mały, jak to możliwe.)

+0

Zrobiłeś kilka bardzo dobrych punktów. Niestety, wciąż mogę odpowiedzieć tylko na jeden głos. – sbi

+2

Dodałbym "standardowo przyjętą konwencję" jest to, że identyfikatory, które są wszystkie czapki są makrami. –

+4

Windows.h przyjmuje wszystkie "standardowo akceptowane konwencje", wyrzuca je przez okno i deklaruje na nich makra. Ale tak, dobra rada. Nie używaj znaków uniwersalnych do niczego innego niż #defines i nie zezwalaj, aby windows.h był widoczny w nagłówkach. – jalf

1

Myślę, że nie będzie problemu, jeśli przekroczysz limit. Ale musisz to zrobić wszędzie, gdzie używasz obu enum & windows.h. Najlepszą rzeczą byłoby przemianowanie twojej przestrzeni nazw.

2

Zmiana nazwy przestrzeni nazw jest najczystszym, najbezpieczniejszym, najbardziej interoperacyjnym rozwiązaniem.

2

Przeskakiwanie po "zmianie nazwy przestrzeni adresowej", po prostu dlatego, że ERROR jest zbyt pospolite i niejasne. Znajdź coś bardziej opisowego.

1

Być może zechcesz zreorganizować swój kod, aby ten #include pojawiał się tylko w razie potrzeby. "Prawidłowy" sposób może nawet wymagać utworzenia osobnych plików i nagłówków, które będą zawierać interfejsy do funkcji, które wywołasz z Windows.h

Jeśli jednak potrzebujesz prostej poprawki i jesteś zaniepokojony efektami ubocznymi od #undef ERROR tylko przedefiniować ERROR po zakończeniu z deklaracją:

 
#undef ERROR 
namespace ERROR { 
#define ERROR 0 

trzeba by zrobić to za każdym razem ERROR określany jest (a nie w ciągu).

Powiedziawszy to, powinieneś być w porządku, jeśli po prostu nie zdefiniujesz BŁĘDU. Wpłynęłoby to tylko na to, jak procesor C obsługuje BŁĄD (a raczej jak nie) od tego momentu.

Nawiasem mówiąc, generalnie widziałem, że nazwy we wszystkich wielkich literach są używane tylko do określenia stałych, a nie do typów i przestrzeni nazw. Chciałbym zrewidować moją konwencję nazewnictwa gdybym cię ..

+0

Zły pomysł; nie jest niespotykane, aby firma Microsoft zmieniła definicję # define w nowszych wersjach SDK. Zdarza się to nawet w przypadku stałych (chociaż ERROR prawdopodobnie nie ulegnie zmianie) – MSalters

+0

Masz rację, to nie jest dobra praktyka i łatwo doprowadziłoby do trudnych do debugowania efektów ubocznych, później zakładając, że wartość etykiety zawsze będzie podana stała. Ale w mojej obronie nie była to moja pierwsza sugestia ani moja ostatnia, i nigdy nie powiedziałem nic o poprawnej poprawce, powiedziałem, że była to prosta poprawka (lub szybka naprawa) - i te typy poprawek zwykle powodują trudności w debugowaniu skutki uboczne! – lcv

0

Najlepszym rozwiązaniem jest, aby zmienić schemat nazewnictwa, aby uniknąć wszystkich kapitalizacji, jak inni sugerują:

namespace FANLib { 
    namespace Error { 
    enum Type { 
     /// FSL error codes 
     FSL_Parser_File_IError, ... 

także poza granice: Identyfikatory zacznij od _ lub __. (To jest bardziej skomplikowane, ale twoje życie będzie prostsze, jeśli unikniesz wszystkich nazw zaczynających się od podkreślenia.)

0

Jeśli nie używasz GDI, możesz zdefiniować NOGDI, aby wyłączyć definiowanie makr w WinGDI.h. Here możesz znaleźć inne przydatne opcje.

0

Identyfikatory rozpoczynające się od E i cyfra lub E oraz wielka litera powinny być traktowane jako zastrzeżone, ponieważ takie nowe makra można dodać do <errno.h>.

Powiązane problemy