Warum ist isnan unklar, und wie es zu vermeiden?

Seit isnan kann entweder ein makro (in C++98) oder eine Funktion im Namensraum std (in C++11), ist eine offensichtliche (und möglicherweise naive) Möglichkeit, den code zu schreiben, der funktioniert in beiden Fällen wird illustriert durch dieses einfache Beispiel

#include <cmath>

int main() {
  double x = 0;
  using namespace std;
  isnan(x);
}

Jedoch, kompilieren es gibt Fehler sowohl in GCC (mit -std=c++11) und Clang:

test.cc: In function ‘int main()’:
test.cc:6:10: error: call of overloaded ‘isnan(double&)’ is ambiguous
   isnan(x);
          ^
test.cc:6:10: note: candidates are:
In file included from /usr/include/features.h:374:0,
                 from /usr/include/x86_64-linux-gnu/c++/4.8/bits/os_defines.h:39,
                 from /usr/include/x86_64-linux-gnu/c++/4.8/bits/c++config.h:426,
                 from /usr/include/c++/4.8/cmath:41,
                 from test.cc:1:
/usr/include/x86_64-linux-gnu/bits/mathcalls.h:234:1: note: int isnan(double)
 __MATHDECL_1 (int,isnan,, (_Mdouble_ __value)) __attribute__ ((__const__));
 ^
In file included from test.cc:1:0:
/usr/include/c++/4.8/cmath:626:3: note: constexpr bool std::isnan(long double)
   isnan(long double __x)
   ^
/usr/include/c++/4.8/cmath:622:3: note: constexpr bool std::isnan(double)
   isnan(double __x)
   ^
/usr/include/c++/4.8/cmath:618:3: note: constexpr bool std::isnan(float)
   isnan(float __x)
   ^

Warum ist das zweideutig in C++11-und wie es funktioniert mit C++98 und C++11 vorzugsweise ohne zu viel bedingte Kompilierung?

  • Welche Art ist x?
  • x ist double
  • Sicher. Ich habe das komplette kompilierbare Beispiel
  • Wenn Sie weiterhin die Fehlermeldung erhalten, indem das schreiben (isnan)(x); dann ist es nichts mit Makros
  • Ich habe nicht die Fehler, die in g++ 4.9.2 für Windows, aber bekommen es auf godbolt, die verwendet eine Art Linux. Also vielleicht ist es ein bug in der glibc-Header
  • auch etwas von einem bug, dass std::isnan(long double) und std::isnan(float) sind aufgeführt, als könnten Sie nie ausgewählt werden, wie auch immer; die Mehrdeutigkeit ist zwischen ::isnan(double) und std::isnan(double)
  • Schöne Beobachtungen. Ich Frage mich, ob es eine Möglichkeit gibt zu unterscheiden zwischen std::isnan und ::isnan irgendwie.
  • Ist es die nicht-standard-Attribut, das stört, oder die Zweideutigkeit zwischen ::isnan(double) und std::isnan(double)?
  • guter Punkt, der eigentliche Fehler ist, dass es zwei verschiedene Funktionen. Der C++ Standard verlangt, dass, wenn ::isnan vorhanden ist, dann std::isnan muss die gleiche Funktion injiziert namespace std. Die C++ - Bibliothek sollte mittels der C-Bibliothek isnan(double) hinzufügen und nur std::isnan(long double) und std::isnan(float) .
  • Ich denke constexpr hier ist ein bug zu; C++14 [constexpr.Funktionen]/1 sagt, "Eine Umsetzung ist nicht deklarieren der standard-Bibliothek-Funktion der Unterschrift als constexpr, außer denen, wo es explizit gewünscht ist." Der standard legt NICHT fest, dass isnan sollte constexpr.
  • cmath Funktionen constexpr ist ein bekanntes libstdc++ - Problem.
  • es gibt bereits einen bug-report, ich habe es in meiner Antwort.

InformationsquelleAutor vitaut | 2015-11-18
Schreibe einen Kommentar