2013-05-16 7 views
22

Rozważmy:C++ 11 operator "" o podwójnym parametrem

struct str {}; 

str operator"" _X(long double d) { 
    return str(); 
} 

to kompiluje zg ++ 4.7.2 Tablica std = C++ 11

ale jeśli dam podwójny:

str operator"" _X(double d) { 
    return str(); 
} 

pojawia się następujący komunikat o błędzie: main.cpp | 3 | błędzie: 'operator str "" _X (podwójne)' ma liście Invalid argument

Na czym polega problem? Czy ma to coś wspólnego z "Nie można ponownie zdefiniować znaczenia wbudowanego dosłownego sufiksu" (Stroustrup FAQ)? Czy możesz wymyślić obejście?

Odpowiedz

31

What is the problem?

Problem polega na tym, że standard zabrania tego. Zgodnie z pkt 13.5.8./3 w C++ 11 Standardu zdefiniowanych przez użytkownika literałów:

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 

dotycząca obejścia, nie jestem pewien, że to jest potrzebne, ponieważ następujący działa dobrze (a double dostaje niejawnie przerobiony na long double, więc można przekazać w literałów typu double):

struct str {}; 

str operator"" _X(long double d) { 
    return str(); 
} 

int main() 
{ 
    str s = 4.0_X; 
} 
+3

Ok dzięki. Ale dlaczego ? Mam na myśli, czy było coś w składni, która uniemożliwiała podwójne podwojenie? –

+5

@ BérengerBerthoul: Dlaczego używałbyś 'double', gdy' long double' ma tyle lub więcej zasięgu i precyzji? Prawdopodobnie ze względu na szybkość lub użycie pamięci, prawda? Cóż, nie są to uwagi dotyczące operacji wykonywanych podczas kompilacji. Jeśli chcesz wykonywać operacje z podwójną precyzją, zawsze możesz użyć rzutowania wewnątrz funkcji. –

+0

@Ben Voigt Ok, w porządku dla mnie. Po prostu myślę, że to trochę kludge, ale w rzeczywistości nie ma dużego pb. Dzięki –

3

myślę, że aby zapobiec przeciążeniom niejednoznaczne. Co zrobić, jeśli wolno było określić następujące przeciążenie ustawić

str operator"" _X(long double ld); 
str operator"" _X(double d); 
str operator"" _X(float f); 

Czy możesz podać przykłady zdefiniowanych przez użytkownika literały w kodzie źródłowym, która będzie mapować do każdego z powyższych? Nie, nie ma sposobu na ograniczenie dosłowności do konkretnego typu danych zmiennoprzecinkowych.

Co może być przydatny jest ten zestaw:

str operator"" l_X(long double ld); 
str operator"" _X(long double d); 
str operator"" f_X(long double f); 

Od teraz można napisać

3.0_X // treated like a double 
3.0l_X // treated like a long double 
3.0f_X // treated like a float 
+0

Jest to możliwe, ale nie tak myślę. Będzie to sprzeczne z filozofią C++, która umożliwi strzelanie sobie w stopę, jeśli jednocześnie uzyskasz korzyści. I rzeczywiście przyniosłoby to korzyści. Na przykład w moim prawdziwym kodzie, struktura "str" ​​jest szablonem, aw szczególności tworzona jest dla "podwójnego". I do tego nie mogę użyć "długiej podwójnej" sztuczki (z wyjątkiem specjalizacji, ale to naprawdę staje się kludgy, a np.częściowa specjalizacja jest niedozwolona dla funkcji ...) –

+1

@ BérengerBerthoul: Możesz napisać swojego operatora jako operatora 'str " "_X (long double ld) {double d = ld;/* użyj d * /} ' –