2013-05-16 38 views
22

xem xét:C++ 11 nhà điều hành "" với tham số đôi

struct str {}; 

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

này biên dịch tốt với g ++ 4.7.2 Tường std = C++ 11

nhưng bây giờ nếu tôi đưa ra một đôi:

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

tôi nhận được thông báo lỗi sau: main.cpp | 3 | lỗi: 'điều hành str "" _x (double)' có danh sách đối số không hợp lệ

Vấn đề là gì? Có điều gì đó liên quan đến "Không thể xác định lại ý nghĩa của hậu tố chữ" (Stroustrup FAQ)? Bạn có thể nghĩ ra cách giải quyết không?

Trả lời

31

What is the problem?

Vấn đề là tiêu chuẩn cấm. Mỗi đoạn 13.5.8./3 của C++ 11 tiêu chuẩn về người dùng định nghĩa literals:

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 

Về một workaround, tôi không chắc chắn nó là cần thiết, kể từ sau hoạt động tốt (một double được ngầm chuyển đổi sang một long double, vì vậy bạn có thể vượt qua trong literals kiểu double):

struct str {}; 

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

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

Ok cảm ơn. Nhưng tại sao ? Ý tôi là, có điều gì đó trong cú pháp ngăn cản không thể tăng gấp đôi? –

+5

@ BérengerBerthoul: Tại sao bạn lại sử dụng 'double' khi 'long double' có nhiều hoặc nhiều độ chính xác? Có lẽ vì lý do tốc độ hoặc sử dụng bộ nhớ, phải không? Vâng, đó không phải là những cân nhắc cho các hoạt động được thực hiện tại thời gian biên dịch. Nếu bạn muốn thực hiện các phép toán với độ chính xác gấp đôi, bạn luôn có thể sử dụng một phép đúc bên trong hàm. –

+0

@Ben Voigt Ok, tốt cho tôi. Tôi chỉ nghĩ rằng đó là một chút kludge, nhưng thực sự không có pb lớn. Cảm ơn –

3

tôi nghĩ đó là để ngăn ngừa quá tải mơ hồ. Điều gì sẽ xảy ra nếu bạn được phép xác định bộ quá tải sau đây

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

Bạn có thể đưa ra các ví dụ về mã nguồn do người dùng xác định trong bản đồ sẽ ánh xạ tới từng thứ ở trên không? Không, không có cách nào để hạn chế chữ cái thành một kiểu dữ liệu dấu chấm động cụ thể.

Điều gì có thể hữu ích là nhóm này:

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

Kể từ bây giờ bạn có thể viết

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

Có thể, nhưng tôi không nghĩ vậy. Nó sẽ đi ngược lại triết lý C++ để cho phép tự bắn mình vào chân nếu đồng thời bạn có thể nhận được lợi ích. Và thực sự điều này sẽ có lợi ích. Ví dụ, trong mã thực sự của tôi, struct "str" ​​là mẫu, và đặc biệt là instantiated cho "double". Và vì điều đó tôi không thể sử dụng mẹo "dài gấp đôi" (ngoại trừ chuyên môn hóa, nhưng điều này thực sự trở thành kludgy, và ví dụ:chuyên môn hóa một phần không được phép cho các chức năng ...) –

+1

@ BérengerBerthoul: Hãy viết toán tử của bạn là 'str toán tử" "_X (dài gấp đôi ld) {double d = ld;/* sử dụng d * /} ' –