2013-03-04 14 views
18

common_type<long, unsigned long>::typeunsigned long ist, weil in Bezug auf die Operanden nach integraler Förderung des Standard sagt ...Warum ist common_type <long, unsigned long> :: type = long lang nicht?

[...], wenn die Operanden, die unsigned integer Typen hat haben Rang größer oder gleich den Rang des Typs des anderen Operanden, die Operanden mit integer-Typ unterzeichnet wird mit unsigned integer Typ

Nicht rufen sie die integrale Förderung System fehlerhaft, aber es scheint, wie der Art des Operanden umgewandelt werden, wenn es eine größere signed Integer Typ wh Ich kann den Bereich von sowohl signierten als auch vorzeichenlosen Operanden darstellen, die verwendet werden sollten.

Ich weiß, dass einige Plattformen könnten lange == lange lange, wobei in diesem Fall die obige Regel wirksam werden. Aber wenn es ein größerer unterzeichnete integralen Typen verfügbar ist, sollte es nicht verwendet werden?

+4

Ich glaube nicht, dass es keine Garantie ist, dass 'lange long' den gesamten Bereich der' unsigned long' umfassen wird. Wenn es wie der Rest der Größenspezifikationen ist, ist die einzige Anforderung, dass es mit mindestens so vielen Bits wie "lang" dargestellt wird. Die Typ-Promotion sollte sich unabhängig von der Plattform einheitlich verhalten, daher gibt es eine gewisse Vorhersagbarkeit hinsichtlich der Überladungsauflösung. – jpm

+2

'std :: common_type' stimmt mit den Regeln zur Bestimmung des Rückgabetyps des ternären Operators überein. In diesem Licht erscheint es offensichtlich falsch, dass der ternäre Operator einen Typ zurückgibt, der größer ist als jeder seiner beiden Zweige. –

+0

@KevinBallard Ich glaube nicht, dass das offensichtlich falsch scheint.Einen Typ zurückzugeben, der größer ist als jeder seiner Zweige, wenn die Zweige unterschiedlich signiert zurückkommen, scheint das einzige zu sein, was garantiert fehlerfrei ist. – David

Antwort

6

zunächst, std :: common_type (und natürlich auch boost :: type_traits :: common_type) den ternären Operator den Typ Ergebnis abzurufen. In diesem Fall kommt das entsprechende Zitat aus den CppReference, 6b)

E2 und E3 haben arithmetische oder Aufzählungstyp: übliche arithmetische Umwandlungen werden angelegt, um sie gemeinsam Typen zu bringen, diese Art ist das Ergebnis.

Mit diesen Informationen wir die Regeln für die üblichen arithmetischen Umwandlungen im c++ standard, 5P10, Seite 88.

finden können - Andernfalls, wenn die Operanden, unsigned Integer-Typ hat Rang größer als oder gleich dem Rang des Typs des anderen Operanden wird der Operanden mit signierten integer-Typ auf den Typ des Operanden mit unsigned integer-Typ umgewandelt werden.

Also im Grunde ist die Antwort auf Ihre Frage: ... weil der Standard sagt so.

Aber Sie sind nicht der einzige zu finden, um dieses Verhalten unerwartet. Hier ist ein schnelles runnable Beispiel, um zu versuchen:

#include <iostream> 
#include <typeinfo> 
#include <type_traits> 

int main(int argc, const char* argv[]) 
{ 

    std::cout << typeid(std::common_type<char, unsigned char>::type).name() << std::endl; 
    // I would expect "short", and the result is "int", ok so far. 

    std::cout << typeid(std::common_type<short, unsigned short>::type).name() << std::endl; 
    // I would expect "int", and the result is "int", yay. 

    std::cout << typeid(std::common_type<int, unsigned int>::type).name() << std::endl; 
    // I would expect "long", but the result is "unsigned int" 

    std::cout << typeid(std::common_type<long, unsigned long>::type).name() << std::endl; 
    // I would expect "long long", but the result is "unsigned long" 


    // So this usual arithmetic conversion can lead to unexpected behavior: 
    auto var_auto = true ? var_i : var_ui; 
    std::cout << typeid(var_auto).name() << std::endl; // unsigned int 
    std::cout << var_auto << std::endl;     // 4294967173 

    return 0; 
} 

aber, dass das derzeitige Verhalten ist ein Problem known ist, und ein proposal existieren einige der Überraschungen zu entfernen.

-Hannes

+0

Also, was ist deine Frage? Ich antwortete: "Warum ist common_type :: type = long lang?" Dein Beispiel fügt nicht mehr Informationen als mein Beispiel hinzu, korrigiere mich, wenn ich falsch liege. Aber natürlich 1 <* MaxULong * -1 ... –

+0

Es war klar in der Frage, dass der Standard tatsächlich sagt, dass es so ist, ich brauchte keine Antwort, die bestätigt, dass es so ist * weil der Standard es so sagt * . Aber wie gesagt, ich bin froh, dass du deine Links unten hast, sie sind relevant und eine teilweise Antwort (insofern es ein bekanntes "Problem" ist, aber nicht zeigt, warum es so war) – David

Verwandte Themen