2014-06-24 11 views
13

Gần đây tôi đã yet again encountered các ký hiệuLàm thế nào là nó phân tích cú pháp: xây dựng giấu tên tạm thời với danh sách init chuẩn bị tinh thần

(const int[10]){ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 } 

Như tôi nhớ lại nó cho phép trong cả C và C++, nhưng qua cơ chế ngôn ngữ hoàn toàn khác.

Tôi tin rằng trong C++ quan điểm chính thức là nó là một xây dựng một tạm thời giấu tên thông qua một loại epxlicit chuyển đổi (T)đúc biểu rằng sẽ làm giảm tới một static_cast, mà xây dựng một đối tượng qua 11 §5.2 C++ 0,9/4:

một biểu e thể được chuyển đổi một cách rõ ràng cho một loại T sử dụng một static_cast dạng static_cast<T>(e) nếu việc kê khai T t(e); là tốt được hình thành, đối với một số phát minh tempor ary biến t (8,5)

Tuy nhiên, dàn diễn viên thể hiện cú pháp được xác định bởi C++ 11 §5.4/2 như là một trong hai unary thể hiện hay, đệ quy, một (loại-id)biểu thức truyền, trong đó trường hợp cơ sở đơn lẻ bị giảm xuống biểu thức đơn nhất.

Và theo như tôi có thể cho biết init-list có sẵn không phải là một biểu thức?

Một quan điểm khác có thể là nó ’ là một loại chuyển đổi rõ ràng thông qua ký hiệu chức năng, C++ 11 §5.2.3/3,

một đơn giản-type-specifier hoặc typename-specifier theo sau là một chuẩn bị tinh thần-init-list tạo ra một đối tượng tạm thời của các loại quy định

nhưng theo như tôi có thể nói đơn giản-loại-specifier có thể ’ t liên quan đến dấu ngoặc đơn, và typename-specifier liên quan đến từ khóa typename?

+5

Đây không phải là hợp pháp C++. Sau đây là cách chính xác: 'Bí danh {...}'. – Xeo

+0

@Xeo Bí danh 'Bí danh 'phải làm gì? –

+0

'mẫu sử dụng Alias ​​= T;', chỉ đơn giản là sử dụng bí danh để làm cho mã có thể phân tích cú pháp. – Xeo

Trả lời

6

mỗi C99 (tốt, thực sự N1256 là dự thảo trước) 6.5.2.5/4:

Một biểu thức postfix bao gồm một loại tên trong ngoặc đơn theo sau là một danh sách cú đúp kín của initializers là một hợp chất theo nghĩa đen. Nó cung cấp một đối tượng chưa đặt tên có giá trị được đưa ra bởi danh sách khởi tạo.

Một số trình biên dịch - at least g++ and clang - cung cấp các ký tự hợp chất C99 trong C++ làm phần mở rộng.Ngữ nghĩa, khái niệm

(const int[10]){ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 } 

là một chữ kiểu const int[10]: decltype((const int[10]){ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }) là trong thực tế const int[10]. Lưu ý tốt: Có một số bất đồng giữa các phiên bản g ++ về loại chính xác: phiên bản g ++ trước 4.9 cho biết decltype((const int[10]){ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 })const int(&)[10]. See this demonstration program.

Bạn có thể đạt được kết quả tương tự trong tiêu chuẩn C++ với loại chuyển đổi rõ ràng thông qua ký hiệu chức năng, nhưng bạn phải xác định một loại bí danh cho các loại mảng kể từ khi ký hiệu chức năng đòi hỏi một đơn giản-type-specifier:

using foo = const int[10]; 
foo{ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; 

hoặc Xeo's general alias template:

template <typename T> 
using foo = T; 
foo<const int[10]>{ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; 
+0

** + 1 ** Cảm ơn bạn đã xem C này. Khi nó bật ra, mã C + + không biên dịch được với Visual C++ và với g ++ 4.8.2 khi '-pedantic' được chỉ định. Nếu không có '-pedantic' g ++ chấp nhận mã, có lẽ là một ký tự hợp chất C99 được sử dụng như là một phần mở rộng C++. –

+0

Tại sao phải trả giá? Nó không phải là tạm thời và có thể lấy địa chỉ của nó trong C tốt. Trong thực tế, p5 của cùng một đoạn nói 'Trong cả hai trường hợp, kết quả là một lvalue.' – Cubbi

+0

@Cubbi Bạn tất nhiên là đúng, tôi đã mong đợi' decltype ((const int [10]) {10, 9, 8, 7, 6, 5, 4, 3, 2, 1}) 'là' const int (&) [10] 'để chỉ ra một giá trị, trong khi thực tế nó chỉ đơn giản là' const int [10] 'giống như một chữ của bất kỳ loại nào khác. – Casey

Các vấn đề liên quan