2013-08-08 15 views
6

Z Mingw 4.7.2, mam bibliotekę, która nie kompiluje się z powodu połączenia z isnan. Kompilator mówi "wszystko będzie dobrze", jeśli użyję std::isnan i rzeczywiście uda mi się skompilować mój plik.Czy isnan w std :: namespace? Bardziej ogólnie, kiedy jest std :: konieczny, opcjonalny lub którego należy unikać?

Ale jeśli mogę sprawdzić here (EDIT: ale może powinienem był sprawdzany także here :-)), przy czym std:: nie wydaje się konieczne. Jeśli go dodam, czy plik będzie przenośny?

Ogólnie rzecz biorąc, czy w przypadku każdego przypadku istnieje ogólny sposób zrozumienia, kiedy konieczne jest wprowadzenie numeru std:: (w celu przeniesienia), opcjonalnego lub którego należy unikać?

Edit

Rzeczywiście wśród genezy problemu jest to, że istnieje wiele wtrąceń nagłówka, a niektóre z zawartych nagłówków obejmują <cmath>, a ten plik cpp próbuje zawierać <math.h> (gdy <cmath> został już uwzględniony).

+1

Nie zaznaczaj tutaj, sprawdź [tutaj] (http://en.cppreference.com/w/cpp/numeric/math/isnan). –

+0

@ChristianRau Więc w zasadzie w C++ 98 to nie istniało, i można mieć to tylko poprzez pożyczenie go od C! To interesujące! – Antonio

+0

Nie, zawsze tak było. Ten link powinien tylko pokazać ci, że przed nazwą funkcji znajduje się duże 'std ::'. Przez przypadek ta konkretna funkcja 'isnan' jest obsługiwana tylko w C++ 11 i nie istniała w ogóle w C++ 98 (nawet w nagłówku C, który był nagłówkiem C89/90, a nie nagłówkiem C99, który C++ 11 zastosowań). Więc w pewnym sensie możesz wypożyczyć go z C, ale nie z C zawartego w C++, ale z rzeczywistego C99 (chociaż to powinno być dziwne połączenie). –

Odpowiedz

12

Zależy od tego, który nagłówek należy dołączyć. Jeśli umieścisz nagłówek C <math.h> (który jest częścią C++, choć oznaczony jako przestarzały), możesz użyć niewykwalifikowanych funkcji języka C, takich jak isnan. Jeśli z drugiej strony to C++ nagłówek <cmath>, jesteś tylko gwarantowana że łączy wszystkie funkcje z <math.h> do nazw std a zatem trzeba odpowiednio je zakwalifikować, jak std::isnan (lub użyć jakiegoś dyrektywy using) .Niestety implementacja jest dozwolone ale nie wymaga przynieść te funkcje w globalnej przestrzeni nazw, też, gdy w tym <cmath> (a więc jest to jeden z wielu „działa na moim komputerze” -incidences C++ i rozumu dlaczego wielu ludzi pisze kod tak, jakbyś próbował skompilować bez powodzenia).

Więc Podsumowując: czy to <math.h> i używać isnan lub zawierać <cmath> i używać std::isnan, wszystko inne nie jest przenośny. Oczywiście wszystko to dotyczy również innych nagłówków C i ich wersji C++.

EDIT: Należy zauważyć jednak, że ta szczególna funkcja isnan jest obsługiwana tylko od C++ 11 i nie był dostępny w C++ 98 w ogóle (co może być częścią błąd). Ale to nie zmienia niczego w tej sytuacji, ponieważ w C++ 98 ani <cmath> ani (który był rzeczywistym nagłówkiem C89/C90, a nie nagłówkiem C99, który zawiera C++ 11) miał tę funkcję, ponieważ " zawsze są niezsynchronizowane. Tak więc, ta biblioteka z twojego pytania może być próbowana, to użycie C++ 98 podczas korzystania z funkcji isnan z innej implementacji C99 (co nie jest szczególnie dobrym pomysłem, ponieważ może kolidować z częściami C89/C90 implementacji C++ , nawet tego nie próbowałem).

+0

Tak jest przestarzałe! W C++ 98 należy użyć tylko ? I czy kod, który działa zarówno w C++ 98 jak i C++ 11 byłby możliwy? – Antonio

+0

@Antonio Cały ten problem nie ma nic wspólnego z C++ 98 i C++ 11. Zawsze było tak, jak opisano w mojej odpowiedzi, bez względu na standard C++. I tak, nagłówki C są nazywane przestarzałymi, ale w praktyce to naprawdę niewiele znaczy, a to raczej kwestia gustu, którego używasz (ja sam, będąc dość anty-C snobem i wielkim fanem spamowania 'std ::' wszędzie, wolą jednak nagłówki C++). Ale powinieneś pozostać konsekwentny, w przeciwnym razie zdarza ci się doświadczyć takich dziwactw, jak naprawdę. –

+0

[to zostało napisane przed twoją uwagą] Patrząc na komentarz Christiana Rau'a/link powyżej: isnan '' '' should not be there there in C++ 98 ... I jedyny isnan dla C++ 98 byłby w przestarzałe '', które musi zostać wywołane bez 'std ::'. Tak więc być przenośnym jest ... niemożliwe :) chyba, że ​​umieszczenie jakiegoś kłopotliwego kompilacji warunkowej. – Antonio

2

To dlatego, że isnan pochodzi z C. Używanie innego typu include doprowadzi do różnych wyników. Weź isnan z C nagłówku <math.h> jako przykład:

Jeśli używasz #include <cmath>, zostanie ona umieszczona w przestrzeni nazw std.

Jeśli użyjesz #include <math.h>, zostanie on umieszczony w globalnym obszarze nazw.

C++ 11 D.5 C nagłówki biblioteki standardowej

Każdy nagłówek C, z których każda ma nazwę name.h formie, zachowuje się tak, jakby każda nazwa umieszczona w standardowej przestrzeni nazw biblioteki przez odpowiedni nagłówek cname znajduje się w zasięgu globalnego obszaru nazw. Nie jest sprecyzowane, czy te nazwy są najpierw zadeklarowane, czy zdefiniowane w zasięgu przestrzeni nazw (3.3.6) przestrzeni nazw, a następnie są wtryskiwane do zakresu globalnego obszaru nazw za pomocą jawnych deklaracji użycia (7.3.3).

[Przykład: Nagłówek zapewnia z pewnością deklaracje i definicje w przestrzeni nazw standardowej. Może również udostępniać te nazwy w globalnej przestrzeni nazw. Nagłówek zapewnia zapewne takie same deklaracje i definicje w globalnej przestrzeni nazw, podobnie jak w standardzie C. Może również udostępniać te nazwy w standardzie przestrzeni nazw. -end example]

5

C nie ma pojęcia przestrzeni nazw. Podczas pisania #include <math.h> wszystkie nazwy zadeklarowane w nagłówku przechodzą do globalnej przestrzeni nazw i musisz napisać isnan.

C++ ma przestrzenie nazw. Mimo to, kiedy piszesz #include <math.h> wszystkie nazwy zadeklarowane w nagłówku przejść do globalnej przestrzeni nazw, a trzeba napisać isnan, podobnie jak w C

Ponadto, gdy piszesz #include <cmath> wszystkie nazwy zadeklarowane w nagłówku przejść do przestrzeni nazw std, i musisz napisać std::isnan.

Dalsze implementacje C++ są dozwolone również pójść w drugą stronę, z #include <math.h> umieszczenie nazwiska w stdjak również w globalnej przestrzeni nazw, a także z #include <cmath> umieszczenie nazwiska w globalnej przestrzeni nazw jak również w std. Nie polegaj na tym; kod, który to robi, nie jest przenośny. Jest to ustępstwo dla wdrażających, aby ułatwić sprawę; Oznacza to, że jeśli używasz #include <cmath>, nie możesz założyć, że nie będzie isnan w globalnej przestrzeni nazw, a jeśli użyjesz #include <math.h>, nie możesz założyć, że nie będzie isnan w std.

+0

Co się stanie, jeśli uwzględnię * oba *? (Patrząc na ten konkretny przykład, zachowam niespójne zachowanie) – Antonio

+2

@Antonio Prawdopodobnie zależy to od ich repliki, włącznie z rozkazem i ich strażnikami. W skrócie, * nigdy tego nie rób *. –

+0

@ChristianRau Dzięki, po prostu potrzebowałem autorytatywnej odpowiedzi :) (Nie jestem pisarzem biblioteki) – Antonio

Powiązane problemy