2016-11-23 15 views
35

Dlaczego następujące czynności są nielegalne w C++?Dlaczego nie można używać składni konstruktora w typach "unsigned int"?

auto x = unsigned int(0); 

co następuje po są OK:

auto y = int(0); 
auto z = unsigned(0); 
auto w = float(0); 

lub ogólnie:

auto t = Type(... c-tor-args ...); 

(z wyjątkiem Type jest unsigned int).

+3

Oczywiście można po prostu powiedzieć 'auto' a = 10U ale pewnie wiedział. Składnia, której używasz, nie ma nic wspólnego z konstrukcją, nawet jeśli powierzchownie jest podobna. Użyj literałów właściwego typu i to jest to. –

Odpowiedz

32

Składnia jest Explicit type conversion (functional notation) tutaj. Zgodnie z regułą gramatyczną działa tylko z prostym specyfikatorem typu lub specyfikatorem typedef (tj. Nazwa typu pojedynczego słowa).

(Kopalnia nacisk)

2) Wyrażenie funkcjonalny obsada składa się z prostego typu specyfikatorem lub specyfikatorem typedef (innymi słowy, nazwa typu single-word: unsigned int(expression) lub int*(expression) nie obowiązują), a następnie pojedyncze wyrażenie w nawiasach. To wyrażenie rzutowania jest równoznaczne z odpowiadającym mu wyrażeniem w stylu C w stylu rzutowania.

Można go zmienić na ekspresję c-szarego stylu lub static_cast lub użyć go jako typedef specyfikatorem @ zaproponował Jean-FrançoisFabre.

auto x1 = (unsigned int)(0); 
auto x2 = static_cast<unsigned int>(0); 

cytaty z normą, $5.2.3/1 Explicit type conversion (functional notation) [expr.type.conv]

prosty typ-specyfikator ([dcl.type.simple]) lub TypeName-specyfikator ([temp.res]), a następnie w nawiasach opcjonalnie lista-wyrażeń lub lista usztywnionych-init (inicjalizator) konstruuje wartość określonego typu z danymi inicjalizatora.

I $7.1.7.2/1 Simple type specifiers [dcl.type.simple]

Proste Specyfikatory typu są

simple-type-specifier: 
    nested-name-specifieropt type-name 
    nested-name-specifier template simple-template-id 
    nested-name-specifieropt template-name 
    char 
    char16_t 
    char32_t 
    wchar_t 
    bool 
    short 
    int 
    long 
    signed 
    unsigned 
    float 
    double 
    void 
    auto 
    decltype-specifier 
type-name: 
    class-name 
    enum-name 
    typedef-name 
    simple-template-id 
decltype-specifier: 
    decltype (expression) 
    decltype (auto) 
+0

Zakładam, że "unsigned (0)" również będzie działało. – Asu

+0

@Asu Tak, ponieważ jest to prosty typ specyfikatora. – songyuanyao

+0

Czy możesz określić, skąd pochodzi ten cytat? Dzięki :) – Steve

20

Z powodu priorytetu analizowania. Kompilator zostanie utracony, ponieważ int(0) jest dopasowany przed unsigned int.

Trzeba załączyć typ w nawiasach:

auto x = (unsigned int)(0); 

lub użycie typedef:

typedef unsigned int uint; 
auto x = uint(0); 
+2

Nie jestem pewien, czy "pierwszeństwo operatorów" jest tu właściwym terminem. – juanchopanza

+3

Nie jestem też pewien. Co byś zasugerował? priorytet parsowania? Edytuję w ten sposób. –

+3

Priorytet sortowania jest prawdopodobnie wystarczająco jasny, ale tak naprawdę są to tylko zasady gramatyki języka. Odlewania w stylu funkcji muszą być pojedynczym identyfikatorem. –

Powiązane problemy