Geben Sie die Eigenschaft ein, um die Standardargument-Promotion zu erhalten

8

[Haftungsausschluss: Ich kenne eine Antwort auf diese Frage. Ich dachte, es könnte von allgemeinem Interesse sein.]

Frage: Wie können wir eine Typeigenschaft haben, die den Typ erzeugt, der sich aus der Ausführung von Standard-Argument-Promotions ergibt?

Motivation: Ich möchte in der Lage sein, variable Argumente portabel zu verwenden. Zum Beispiel:

%Vor%

Wenn Argumente einem Funktionsaufruf ohne Parameter übergeben werden, d. h. mit den Auslassungspunkten übereinstimmen, werden die Argumente der Standardargument-Heraufstufung unterzogen. So weit, so gut, aber diese Aktionen sind plattformabhängig. Ich kann die Argumente mit va_arg(ap, T) wiederherstellen, aber was ist T ?

Nun, für einige einfache Situationen ist das einfach: Zum Beispiel kann ich immer sagen:

%Vor%

Das Standard-Angebot wird entweder zu einem signed int oder einem unsigned int führen, aber nach C11 7.16.1.1/3 ist va-casting zu unsigned int immer in Ordnung, auch wenn das Standard-Angebot ist ergibt sich ein int , der ursprüngliche Wert kann durch beide Typen dargestellt werden.

Aber welchen Typ sollte ich einsetzen, wenn ich ein char32_t erwarte? C ++ 11 4.5 / 2 lässt den resultierenden Typ weit offen. Ich hätte gerne eine Eigenschaft, die mich schreiben lässt:

%Vor%

Wie geht das?

Bonuspunkte für eine Eigenschaft, die eine statische Assertion erzeugt, wenn der Parametertyp nicht als variables Argument übergeben werden muss.

    
Kerrek SB 07.12.2013, 14:14
quelle

3 Antworten

3

Hier ist ein Skelett einer Lösung, die für "die meisten" Typen funktioniert (Integral, Float, Uncoped Enumeration, Arrays, Zeiger, Zeiger-zu-Element, Funktionen, Funktionszeiger).

%Vor%

Es bietet keine Diagnose für Typen, die nicht sicher durch eine Ellipse übergeben werden können. Diese Subsumiation subsumiert auch den Zerfall, den Typen erfahren, wenn sie als Variablenfunktionsargumente übergeben werden, so dass es nicht ausschließlich um die Promotion geht.

Dies funktioniert, indem explizit die Pointer-zu-Member-Typen und die Fließkomma-Konvertierung gehandhabt werden, und indem auf den unären Operator + für integrale und nicht gekapselte Aufzählungstypen zurückgegriffen wird; z.B. C ++ 11 5.3.1 / 7:

  

Der Operand des unären + -Operators muss eine arithmetische, nicht gekapselte Aufzählung oder einen Zeigertyp haben, und das Ergebnis ist der Wert des Arguments. Die Integral-Heraufstufung wird an Integral- oder Enumerationsoperanden durchgeführt. Der Typ des Ergebnisses ist der Typ des beworbenen Operanden.

Für die Verarbeitung von Aufzählungen ist etwas zusätzlicher Aufwand erforderlich, da Operatoren für Aufzählungen (sowohl für Bereiche als auch für Bereiche ohne Bereichsbeschränkung) überladen werden können. Daher muss der naive unäre Plus-Operator mit Vorsicht verwendet werden. Das heißt, wir müssen die Förderung des zugrunde liegenden Typs in Betracht ziehen, wenn die Enum-Option nicht gekopiert ist, und verbieten, dass die Bereiche vollständig umschlossen sind.

    
Kerrek SB 07.12.2013 17:49
quelle
2
%Vor%

Wenn es eine One-Liner-Lösung gibt, denke ich über einen Selbstmord nach :) Ich werde das wahrscheinlich mit fits<T, U> template verbessern und ich werde auch das
reparieren Die unelegante wchar_t und char16_t char32_t Codewiederholung.

    
ScarletAmaranth 07.12.2013 15:47
quelle
1

Ich denke, es könnte etwas besser sein, operator+ zu vermeiden. ?: kann nicht überladen werden, die wirklich wichtigen Prüfungen können auch damit ausgeführt werden, und indem der andere Operand ein Literal 0 wird, werden alle Arten von Zeigertypen automatisch richtig behandelt:

%Vor%

Update : Die Übergabe eines beliebigen Typs über ... ist in unevaluated -Ausdrücken gültig, aber in potenziell ausgewerteten -Ausdrücken ist es bedingt unterstützt. Der vollständige Ausdruck in einer constexpr -Funktion ist potenziell ausgewertet und kann verwendet werden, um einen Fehler bei Implementierungen zu erzwingen, die die Übergabe dieses Typs durch ... nicht unterstützen.

    
hvd 07.12.2013 18:23
quelle