9

Ich habe einige der neuen Funktionen von C++ 11 untersucht und bin sehr beeindruckt von einigen von ihnen, insbesondere die benutzerdefinierten Literale. DieseWie kleinste Variable mit C++ 11 benutzerdefinierten Literalen

können Sie Literale des Formulars definieren 999_something wo something Kontrollen, was mit dem 999 getan wird, um die wörtliche zu erzeugen. Also nicht mehr mit verwenden:

#define MEG * 1024 * 1024 
int ten_meg = 10 M; 

Ich dachte, dies wäre schön Unterstrichen in großen Stückzahlen zu implementieren, wie 1_000_000_blah, die die Lesbarkeit von Perl passen würden, obwohl die Idee, dass Perl irgendwie lesbar ist ziemlich witzig scheint Ich :-)

Es wäre auch praktisch für binäre Werte wie 1101_1110_b und 0011_0011_1100_1111_b.

Offensichtlich wegen der _ Zeichen, müssen diese Rohmodus-Typ sein, eine C-Zeichenfolge verarbeiten, und ich bin damit einverstanden.

Was ich kann nicht herauszufinden, wie Sie einen anderen Typ basierend auf der Operandengröße liefern. Zum Beispiel:

1101_1110_b 

sollen eine char (unter der Annahme char 8-Bit natürlich) geben, während:

0011_0011_1100_1111_b 

einen 16-Bit-Typen liefern würde.

Ich kann die Länge des Operanden innerhalb der Literaloperatorfunktion operator"" selbst erhalten (durch das Zählen von Ziffernzeichen), aber der Rückgabetyp scheint auf die Funktion festgelegt zu sein, so dass ich keinen anderen Typ basierend darauf zurückgeben kann.

Kann dies mit einem einzigen Suffix _b innerhalb der benutzerdefinierten Typen Rahmen durchgeführt werden, oder muss ich (_b8, _b16 usw.) und bieten meistens doppelte Funktionen zu spalten auseinander manuell die Typen zurückgreifen zu müssen?

+0

Ich bin nicht sicher, ob das funktioniert, aber Sie könnten versuchen, mehrere Literal-Operator-Vorlagen für verschiedene Bit-Zahlen zu überladen. – celtschk

+1

Es funktioniert anscheinend: http://akrzemi1.wordpress.com/2012/10/29/user-defined-literals-part-iii/ - Ich denke, dass das dort gegebene Template ziemlich einfach zu erweitern sein sollte, um mehr Typen zu unterstützen. – celtschk

+2

Wenn ich noch einmal darüber nachdenke, was wahrscheinlich * nicht * funktioniert, benutzt Unterstriche als Teil der Nummer: IIUC '1101_1110_b' wird * nicht * Aufruf' Operator' "_b' mit (Vorlage) Argument' 1101_1110', aber 'Operator" "_1110_b" mit (Vorlage) Argument '1101'. – celtschk

Antwort

6

Sie müssen wissen, die Größe oh Ihre Zeichenfolge, und die einzige Möglichkeit, das zu erreichen, ist ein Parameter-Pack zu verwenden sizeof... auf. Sie sollten in der Lage sein, zu erreichen, was Sie mit einem variadische Vorlage wollen operator"":

#include <cstdint> 
#include <type_traits> 

template<char... String> 
auto operator "" _b() 
    -> typename std::conditional<sizeof...(String) <= 8, 
     uint8_t, 
     typename std::conditional<sizeof...(String) <= 16, 
      uint16_t, 
      uint32_t 
     >::type 
    >::type 
{ 
    // Do whatever you want here 
} 

Und hier ist ein Testfall:

int main() 
{ 
    auto a = 10000001_b; 
    auto b = 100000001_b; 

    std::cout << std::boolalpha; 
    std::cout << std::is_same<decltype(a), uint8_t>::value << "\n"; // true 
    std::cout << std::is_same<decltype(b), uint16_t>::value << "\n"; // true 
} 

Leider kann diese Lösung nicht die Ziffer Separator behandeln. Darüber hinaus ist die std::conditional Maschinerie ziemlich hässlich. Sie könnten wahrscheinlich etwas besser mit boost::mpl::vector, boost::mpl::at und einige arithmetische Operationen arbeiten.

+0

Und nun ignorieren führende 0s im Typeschluss;) Nein ernsthaft, gute Antwort. –

+2

@ChristianRau Es ist einfacher, Leute zu ignorieren, die Nullen schreiben. Außerdem wäre das ... oktal binär! – Morwenn

+0

@Morwenn: Ich wünschte, C und C++ würden Konstanten ablehnen, die eine führende Null und nichts anderes als Dezimalziffern enthalten, * aber * definieren eine Standardnotation für Oktalkonstanten in einer solchen Weise, dass Code ein Makro definieren könnte (zB __OCT (x)) Makro, das x als Oktalkonstante in beiden Compilerarten interpretieren würde [meine persönliche bevorzugte Notation, aber für die Tatsache, dass es mit der benutzerdefinierten Literalsyntax kollidiert hätte, hätte man sagen müssen, dass 8x1234 eine Oktalkonstante wäre, 0x1234 und 16x1234 wäre hex, 10x0wäre dezimal, usw. Das hätte schön verallgemeinert werden können. – supercat

Verwandte Themen