2015-05-01 7 views
17

Folgende Benutzer literal definiert weglässt einen Fehler:Warum muss ich long double für benutzerdefinierte Literale verwenden?

constexpr double operator "" _kg(double q) 
{ 
    return q*1000; 
} 

aber wenn long der Fehler verschwindet, hinzugefügt wird, und Code funktioniert wie folgt:

constexpr double operator "" _kg(long double q) 
{ 
    return q*1000; 
} 

Der Fehler ist:

‘constexpr double operator""_kg(double)’ has invalid argument list 

Das Problem wird nur durch das Argument verursacht, und der Rückgabetyp kann double ohne long lauten.

Warum wird long benötigt?

+1

'long double' ist ein Typ mit noch mehr Präzision als' double'., Genau wie 'long int' eine größere Variante von' int' ist. –

+1

Wie für Ihr Problem, * was * Fehler bekommen Sie? Bearbeiten Sie Ihre Frage so, dass sie die vollständige und unbearbeitete Fehlerausgabe enthält, * und * ein [minimales, vollständiges und überprüfbares Beispiel] (http://stackoverflow.com/help/mcve), das die Fehler verursacht. –

+0

Ich habe die Frage für weitere Details einschließlich der Fehlermeldung bearbeitet. –

Antwort

21

C++ 11 Entwurf n3290 hat dies über die Parameter zu sagen, dass benutzerdefinierte Literale in Anspruch nehmen (§13.5.8):

The declaration of a literal operator shall have a parameter-declaration-clause equivalent to one of the following:

const char* 
unsigned long long int 
long double 
char 
wchar_t 
char16_t 
char32_t 
const char*, std::size_t 
const wchar_t*, std::size_t 
const char16_t*, std::size_t 
const char32_t*, std::size_t 

Wie Sie sehen können, double ist nicht in dieser Liste, nur long double ist. Sie müssen das also für benutzerdefinierte Literale verwenden, die eine Gleitkommazahl als Argument erwarten.

+0

Irgendeine Idee warum? – nbubis

+0

Nicht wirklich. Ich nehme an, dass sie sich für den größten Typ entschieden haben, den der Standard für die gekochten Literale garantiert. Wenn Sie mehr benötigen, können Sie immer rohe Literale verwenden. Wenn Sie weniger brauchen, gut, schneiden Sie einfach ab. – Mat

+0

Ich vermute der Grund ist, dass für ein Literal Sie die Genauigkeit nicht kennen können. Zum Beispiel haben einige Zahlen eine unendliche lange Darstellung im Fließkommaformat und müssen daher abgeschnitten werden. Es ist sinnvoll, die Literale nicht mehr als nötig abzukürzen. – danijar

3

Only the following parameter lists are allowed on literal operators :

  • (const char *) (1)
  • (unsigned long long int) (2)
  • (long double) (3)
  • (char) (4)
  • (wchar_t) (5)
  • (char16_t) (6)
  • (char32_t) (7)
  • (const char * , std::size_t) (8)
  • (const wchar_t * , std::size_t) (9)
  • (const char16_t * , std::size_t) (10) (const char32_t * , std::size_t) (11)

    1. Literal operators with this parameter list are the raw literal operators, used as fallbacks for integer and floating-point user-defined literals (see above)

    2. Literal operators with these parameter lists are the first-choice literal operator for user-defined integer literals

    3. Literal operators with these parameter lists are the first-choice literal operator for user-defined floating-point literals

4-7. Literal operators with these parameter lists are called by

user-defined character literals

8-11. Literal operators with these parameter lists are called by user-defined string literals

Default arguments are not allowed C language linkage is not allowed Other than the restrictions above, literal operators and literal operator templates are normal functions (and function templates), they can be declared inline or constexpr, they may have internal or external linkage, they can be called explicitly, their addresses can be taken, etc.

Von CPP Referenz: http://en.cppreference.com/w/cpp/language/user_literal

0

Obwohl der Ausfall ANSI C eine Form mit variabler Argument Erklärung zu definieren, die sauber ein erweiterter Genauigkeit long double Typ, dessen handhaben kann Format unterscheidet sich von der von double geführt hat zu dem Typ ist effektiv veraltet auf vielen Plattformen (unglücklicherweise, IMHO, da es ein guter Typ für den Einsatz nicht nur auf Systemen mit x87 Coprozessoren war, sondern auch auf Systemen ohne FPU), der einzige vernünftige Weg für ein System mit richtig erweitert -precision Typen, um eine Aussage wie zu behandeln:

long double a = 0.1; 

ist das 0,1 Zahlenliteral Start Leben als long double gleich 14,757,395,258,967,641,293/147,573,952,589,676,412,928 zu haben; es wäre absurd, diese Aussage a zu 7,205,759,403,792,794/72,057,594,037,927,936 (ungefähr 0,10000000000000000555, der Wert von (double)0.1) zu setzen.

könnte es wohl ein paar Fälle, in denen als long double vor immer umgewandelt Abwärts Zahlenliteral Start Leben mit könnte es dazu führen, von einem anderen Wert zu erhalten, was wäre es, wenn sie das Leben als double oder float gestartet (zB der nächste float zu 9007199791611905.0 ist 9007200328482816, was 536870911 über dem angeforderten Wert ist, aber (float)(double)9007199791611905.0 ergibt 9007199254740992, was 536870913 darunter ist. Natürlich, wenn man den Float-Wert 9007200328482816.0f möchte, sollte man wahrscheinlich eine dezimale Darstellung verwenden, die näher ist was man wirklich will.