2016-03-30 9 views
0

In libC++ auf 32-Bit-Plattformen ist int64_t als Alias ​​von long long definiert. Auf 64-Bit-Plattformen: long.Clang's libC++: long long in der Definition von std :: chrono :: duration verwenden

Auf der anderen Seite in der Definition von std::chrono::duration Aliase, dass Sie finden herelong long nachlässig verwendet wird:

typedef duration<long long,   nano> nanoseconds; 
typedef duration<long long,  micro> microseconds; 
typedef duration<long long,  milli> milliseconds; 
typedef duration<long long    > seconds; 
typedef duration<  long, ratio< 60> > minutes; 
typedef duration<  long, ratio<3600> > hours; 

So zum Beispiel, wenn ich Typen erfordern, die streng 8 Bytes lang ist, würde ich

erwarten
foo(uint64_t); 
    foo(int64_t); 

eine ziemlich portable Lösung sein. Aber im Falle von libC++ chrono ist es nicht wahr. Es gibt keinen tragbaren Weg, außer dass Sie Ihre eigene Logik ähnlich wie <cstdint> schreiben. Dh, definieren zwei zusätzliche Definitionen von foo, die long long und unsigned long long übernehmen.

Oder ein anderes Beispiel:

foo(int8_t); 
    foo(int16_t); 
    foo(int32_t); 
    foo(int64_t); 

foo(duration.count()) aufrufen würde in diesem Fall nicht eindeutig sein.

Also was ist der Punkt der Verwendung von long long, die nicht größer ist als long, aber es ist Rang größer als long, so dass es nicht implizit gegossen werden kann?

Ist dies ein Versehen von Entwicklern von libc++?

Der Grund, warum ich dies heraufgebracht habe, ist, weil Treiber von mongodb nicht auf x64 FreeBSD Installation kompilieren. Und der Grund sieht ziemlich albern aus. Zum Beispiel gcc verwendet int64_t in den Definitionen von std::chrono::duration und so kompiliert, wie erwartet.

+0

Es gibt 64-Bit-Plattformen, bei denen 'long' 32 Bit ist. Überprüfen Sie den Unterschied zwischen LP64 und LLP64-Plattformen. Beachten Sie, dass dies sogar compilerspezifisch ist, nicht nur für die Plattform, obwohl in der Regel bestimmte Konventionen existieren. –

+0

@UlrichEckhardt natürlich gibt es, aber was hat das zu tun, die Frage? Bibliothek definiert '', warum also nicht für die Portabilität anderer Teile der Bibliothek verwenden? – GreenScape

+0

Mein Punkt ist, dass Sie Satz ist falsch und, vorausgesetzt, ich verstehe dein Problem, völlig irrelevant! Geht es nicht um die Frage "Warum ist" duration "mit" uint64_t "auf einer Plattform definiert und" long long "auf einer anderen?" Übrigens: Hast du einen Link für die mongodb Build Probleme? –

Antwort

5

Der Standard erfordert nur seconds ist ein typedef für duration mit einem Verhältnis von 1 und einem "signed Integer-Typ von mindestens 35 Bits". So ist die Implementierung von libC++ korrekt.

Während der Verwendung von int64_t würde Portabilität in Ihrem speziellen Fall erleichtert haben, das würde Sie nur so weit tragen. MSVC verwendet auch long long, nicht int64_t. (In diesem Fall sind sie jedoch vom selben Typ.) Der Standard garantiert nicht int64_t für die Dauer, daher ist es nicht tragbar, sich darauf zu verlassen, selbst wenn eine weitere Implementierung es benutzt.

Das Problem hier ist nicht, dass die Implementierung von libC++ etwas Schlimmes tut. Das Problem ist, dass die Integer-Typen von C++ etwas verrückt sind, und obwohl die intNN_t Typen bequem sind, befreien sie Sie nicht völlig davon, über die zugrundeliegenden Typen zu wissen. Insbesondere ist der Versuch, eine vollständige Überladung zu erstellen, wie sie für diese Typenschlüssel mit foo dargestellt wird, einfach falsch; Sie müssen für die zugrunde liegenden Typen genau wegen des Problems gehen, auf das Sie gestoßen sind: Die Überladungsgruppe kann long long abdecken oder nicht und Sie werden schließlich in diesen Typ geraten. Dass es mit libC++ duration typedefs statt einer anderen Situation passiert ist, ist nur Zufall.

Ja, es ist eine schlimme Situation, aber dieses spezielle Problem ist nur ein kleines Symptom für das größere Problem.

+0

Stimmen Sie vollständig auf das Problem des Integer-Systemtyps zu. Dank "C" ist es total verschraubt. Auf der anderen Seite, würden Sie mehr Bewusstsein von Entwicklern solcher progressiven Bibliothek erwarten :( – GreenScape

1

Für die Darstellung der Dauer benötigt der Standard keinen bestimmten Integer-Typ. Es erfordert, dass der Typ als rep Mitgliedstyp verfügbar ist, so dass Sie (z. B.) std::chrono::duration::seconds::rep als einen Typ verwenden können, der zum Speichern von Werten in Sekunden geeignet ist.

2

Ich kann mit einer Autorität in dieser Frage sprechen, da ich derjenige war, der diesen Code schrieb. Obwohl die anderen beiden Antworten sehr gut sind und ich sie aufgewertet habe.

Ja, ich habe über diese Typen nachgedacht und überlegt, sie in Bezug auf die int_t*typedef s zu definieren.

Ich wählte long long für die Wiederholungen, die mehr als 32 Bits sein mussten, und long für den Rest. Letzteres wurde mit dem Wissen gemacht, dass sich long von 32 Bits zu 64 Bits ändern würde, wenn das Ziel von i386 zu x86_64 geändert wird.

hatte ich die int_t*typedef s stattdessen verwendet es durchaus möglich ist, dass andere über Mehrdeutigkeit Probleme (etwa zwischen foo(int) und foo(long long)) mit diesem Design als auch beschwert hätte. Es ist schwer zu gefallen jeder.

Ich nehme zur Kenntnis, dass in der mongodb Kopf Mongo/src/Mongo/util/time_support.h heißt es:

using Microseconds = stdx::chrono::microseconds; 
using Milliseconds = stdx::chrono::milliseconds; 
using Seconds = stdx::chrono::seconds; 
using Minutes = stdx::chrono::minutes; 
using Hours = stdx::chrono::hours; 

Dies könnte genauso gut aussehen:

using Microseconds = stdx::chrono::duration<std::int64_t, stdx::chrono::microseconds::period>; 
using Milliseconds = stdx::chrono::duration<std::int64_t, stdx::chrono::milliseconds::period>; 
using Seconds = stdx::chrono::duration<std::int64_t, stdx::chrono::seconds::period>; 
using Minutes = stdx::chrono::duration<std::int64_t, stdx::chrono::minutes::period>; 
using Hours = stdx::chrono::duration<std::int64_t, stdx::chrono::hours::period>; 

D.h. Mit der Bibliothek <chrono> können Kunden sehr einfach benutzerdefinierte Einheiten erstellen. Es klingt, als wäre dies eine gute Lösung für mongodb.

+0

Mein Argument ist dies: in C++ 11 Ausschuss, ich möchte fest davon überzeugt sein, machte einen kleinen Schritt, um Portabilitätsprobleme mit verschiedenen Größen bestimmter zu beheben Ganzzahlige Typen auf verschiedenen Plattformen durch Übernahme von '' Es ist ungewöhnlich, die Implementierung der eigentlichen Bibliothek selbst zu sehen, die aus dem gleichen Grund keine eingeführten Typen verwendet: Portabilität. – GreenScape

Verwandte Themen