2014-10-12 18 views
6

Trong tài liệu CppCon 2014 "Type Deduction and Why You Care", Scott Meyers đặt ra câu hỏi tại sao có quy tắc đặc biệt về auto và khởi tạo nhanh trong tiêu chuẩn C++ 11/C++ 14 (câu hỏi bắt đầu at 36m05s).Tại sao có quy tắc khấu trừ loại đặc biệt cho trình khởi chạy tự động và được đặt trong C++ 11/C++ 14?

Ngữ nghĩa của tự động kết hợp với dấu ngoặc đơn-init-list được định nghĩa trong §7.1.6.4/6.


Tôi đã nghĩ về điều đó và không thể đưa ra trường hợp sử dụng. Điều gần nhất mà tôi đã thấy cho đến nay là một ví dụ mà Bjarne Stroustrup đã sử dụng nó.

Trong Cpp 2014 talk "Make Simple Tasks Simple!" của mình, anh ta từng sử dụng auto để bắt người khởi tạo (nhưng chỉ là cách giải quyết).

Đây là mã (một phần của trượt 30, at 37m10s):

// auto ss1 = collect({ 1, 2, 3, 4, 5, 6 }, odd); // error: Bummer! 
    auto lst = { 1, 2, 3, 4, 5, 6 }; 
    auto ss2 = collect(lst, odd); // {1,3,5} 

Nhưng lưu ý rằng nó chỉ là một cách giải quyết. Ông nói rằng nó không cần thiết. Thay vào đó, anh ta muốn trực tiếp truyền các đối số cho hàm. Vì vậy, nó không thể thực sự phục vụ như một động lực tốt cho auto và danh sách khởi tạo.


Hiểu biết của tôi về C++ không đủ sâu để đánh giá nhược điểm của việc cho phép danh sách khởi tạo trong ví dụ của Bjarne, như ông đề xuất. Dù sao, nó sẽ tránh sự cần thiết cho auto trong trường hợp đó.

Vì vậy, là auto và danh sách trình khởi tạo chỉ là giải pháp cho một thứ có thể được giải quyết tốt hơn? Hoặc có những ví dụ hay, trong đó quy tắc khấu trừ tự động bổ sung trong §7.1.4.4/6 có hữu ích không?

+0

Tôi chắc rằng có đề xuất C++ 1z để tạo 'auto x = {expr};' sử dụng loại 'expr' (trừ cho phép toán tử dấu phẩy không được dấu ngoặc đơn). Tôi không chắc chắn loại khác để sử dụng cho một danh sách đầy đủ, mặc dù. – chris

+0

@christ Tôi nghĩ bạn có nghĩa là N3922. Scott Meyers cũng đề cập đến điều đó. Visual Studio đã thực hiện nó, mặc dù nó không phải là một phần của C++ 14. Đây là liên kết: http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2014/n3922.html –

+0

Ah, đó là một. Mặc dù tôi * loại * phải không đồng ý với cái chung vì việc sử dụng này. Tôi thực sự thích rằng để được hình thành bệnh và initializer danh sách có thể được thông qua vào các chức năng mà không có dòng phụ, mặc dù. – chris

Trả lời

8

Lý do là trong N2640, mà muốn cấm trừ một tham số kiểu đơn giản từ một danh sách initializer chuẩn bị tinh thần nói chung:

template<class T> 
void inc(T, int); // (1) 

template<class T> 
void inc(std::initializer_list<T>, long); // (2) 

inc({1, 2, 3}, 3); // Calls (2). (If deduction had succeeded 
        // for (1), (1) would have been called — a 
        // surprise.) 

Nhưng khắc ra một ngoại lệ đặc biệt cho auto:

Mặt khác, có thể suy ra một initializer_list<X> cho T là điểm hấp dẫn đã cho phép:

auto x = { 1, 1, 2, 3, 5 }; 
f(x); 
g(x); 

được coi là hành vi mong muốn từ đầu rất của EWG thảo luận về danh sách khởi tạo. Thay vì đưa ra quy tắc khấu trừ thông minh cho loại tham số T phù hợp với {} -list (tùy chọn chúng tôi theo đuổi trong các bản phác thảo và bản nháp trước của bài viết này), , chúng tôi muốn xử lý điều này với trường hợp đặc biệt cho "auto" biến khấu trừ khi trình khởi tạo là {} -list. Ví dụ: đối với trường hợp cụ thể là của biến được khai báo với trình nhập loại "tự động" và trình khởi tạo danh sách {}, "tự động" được suy ra như đối với hàm f(initializer_list<T>) thay vì đối với hàm f(T).

2

Scott Meyers giải quyết chủ đề này trong một bài viết trên blog: Why auto deduces std::initializer_list for a braced initializer

Giống như câu trả lời T.C., nó cũng đề cập đến N2640. Nguyên tắc khấu trừ đặc biệt đã được thêm vào để cho phép mã như thế này để làm việc:

auto x = { 1, 1, 2, 3, 5 }; 
f(x); 
g(x); 

Trong bài viết trên blog, Scott trích dẫn lời giải thích sau đây từ James Hopkin:

Câu chuyện ngắn gọn là N2640 đề xuất trường hợp đặc biệt mà tự động nên suy ra initialized braced như initializer_lists, mà không nhận ra rằng làm như vậy đã phá vỡ khởi tạo thống nhất (ví dụ như nó làm cho int x{7};auto x{7}; rất khác nhau). N3922 sửa lỗi đó bằng (tất nhiên!) Giới thiệu một trường hợp đặc biệt khác: các trình khởi tạo kết hợp tham số đơn có quy tắc riêng của chúng.

Chi tiết hơn một chút: N2640 cố gắng duy trì tính toán đối số mẫu đơn giản nhưng cố gắng cho phép trình khởi chạy nhanh được chuyển tới hai hoặc nhiều hàm thông qua gán nó cho tự động. Điều này đã trở thành từ ngữ trong N2672. Lưu ý rằng thiết kế trước đó của Stroustrup trong N2532 cho phép khấu trừ initializer_lists cho cả thông số mẫu không bị giới hạn và tự động, nhất quán hơn nhưng cũng phá vỡ khởi tạo đồng bộ.

Không có điều nào trong số này giải thích tại sao N3922 không chỉ loại bỏ trường hợp đặc biệt cho ô tô. Điều đó sẽ không dẫn đến những thay đổi thầm lặng về ý nghĩa của mã và sẽ đơn giản hóa ngôn ngữ.

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