Trình xây dựng phạm vi std :: vector có thể gọi chuyển đổi rõ ràng không?


14

Chương trình sau đây có được hình thành tốt không?

#include <vector>
struct A {
    explicit A(int) {}
};
int main() {
    std::vector<int> vi = {1, 2, 3, 4, 5};
    std::vector<A> va(vi.begin(), vi.end());
}

Theo C ++ 17 [Sequ.reqmts], yêu cầu đối với

X u(i, j);

nơi Xchứa một chuỗi, là:

Tsẽ được EmplaceConstructiblevào Xtừ *i.

Tuy nhiên, trong đoạn trước có ghi rằng:

ijbiểu thị các trình vòng lặp thỏa mãn các yêu cầu của trình vòng lặp đầu vào và tham khảo các phần tử hoàn toàn có thể chuyển đổi thành value_type,

Do đó, dường như cả hai yêu cầu cần phải được đáp ứng: loại giá trị của phạm vi phải được chuyển đổi hoàn toàn thành loại giá trị của container EmplaceConstructible phải được thỏa mãn (có nghĩa là người cấp phát phải có thể thực hiện khởi tạo được yêu cầu) . Vì intkhông hoàn toàn có thể chuyển đổi thành A, chương trình này sẽ không được định dạng đúng.

Tuy nhiên, đáng ngạc nhiên, nó dường như được biên dịch theo GCC .


(Đối với bản ghi, không chỉ gcc: godbolt.org/z/ULeRDw )
Max Langhof

Trong trường hợp này, không yêu cầu chuyển đổi ngầm định, vì hàm tạo rõ ràng đã phù hợp với loại. Tôi nghĩ rằng mô tả là khó hiểu, nhưng xây dựng rõ ràng luôn luôn tốt hơn sau đó ngầm chuyển đổi trước khi xây dựng.
JHBonarius

Câu trả lời:


2

Nó chỉ là một yêu cầu cho các container theo trình tự để hỗ trợ xây dựng từ các trình vòng lặp thỏa mãn các tiêu chí về khả năng chuyển đổi ngầm định.

Điều này không tự nó không cho phép các trình tự trình tự hỗ trợ việc xây dựng đó từ các trình vòng lặp không thỏa mãn các tiêu chí đó theo như tôi có thể nói với 1 . Có quy tắc rõ ràng về điều đó:

Nếu hàm tạo ... được gọi với Kiểu đầu vào không đủ điều kiện làm trình lặp đầu vào , thì hàm tạo sẽ không tham gia vào độ phân giải quá tải.

Không rõ "đủ điều kiện là một trình vòng lặp đầu vào" nghĩa là chính xác trong ngữ cảnh. Đây có phải là cách không chính thức để thể hiện Cpp17InputIterator hay nó cố gắng tham khảo các yêu cầu của i và j? Tôi không biết. Dù được phép hay không, tiêu chuẩn không có yêu cầu nghiêm ngặt để phát hiện ra nó:

[container.requirements.general]

Hành vi của các chức năng thành viên container nhất định và hướng dẫn khấu trừ phụ thuộc vào việc các loại có đủ điều kiện làm trình lặp hoặc phân bổ đầu vào hay không. Mức độ mà việc triển khai xác định rằng một loại không thể là một trình vòng lặp đầu vào là không xác định, ngoại trừ một kiểu tích phân tối thiểu sẽ không đủ điều kiện làm các trình vòng lặp đầu vào. ...

Với giải thích rằng bất kỳ Cpp17InputIterator nào "đủ điều kiện là một trình vòng lặp đầu vào", chương trình ví dụ sẽ không bắt buộc phải được định dạng sai. Nhưng nó cũng không được đảm bảo để được hình thành tốt.

1 Trong trường hợp như vậy, nó có thể được coi là chất lượng của vấn đề triển khai để cảnh báo khi dựa vào nó. Mặt khác, giới hạn chuyển đổi ngầm định này có thể được coi là một khiếm khuyết .


PS Điều này biên dịch mà không có cảnh báo trong Clang (với libc ++) và Msvc.

PPS Từ ngữ này dường như đã được thêm vào trong C ++ 11 (điều này là tự nhiên, khi đó các nhà xây dựng rõ ràng cũng được giới thiệu).


1
Thực sự phụ thuộc vào những gì "không đủ điều kiện là một trình vòng lặp đầu vào" nghĩa là gì. Không giống như ở trên , nó không thực sự nói Cpp17InputIterator, vì vậy tôi không rõ liệu "và đề cập đến các yếu tố hoàn toàn có thể chuyển đổi thành value_type" được bao gồm trong "trình lặp đầu vào". Nếu đúng như vậy, thì hàm tạo không nên tham gia vào độ phân giải quá tải và chương trình sẽ không được định dạng.
Max Langhof

1
Vì vậy, mỗi lớp thư viện tiêu chuẩn được phép có thêm các hàm tạo mà không đưa ra chẩn đoán khi các hàm xây dựng bổ sung đó được sử dụng? Điều đó theo trực giác có vẻ sai đối với tôi ...
Brian

@Brian Tôi không chắc chắn nếu "các nhà xây dựng bổ sung" của mình, nhưng có thể "triển khai cụ thể hơn các nhà xây dựng cho phép có nhiều phòng hơn". Kiểm tra mọi đầu vào có thể có tác động hiệu suất đáng kể, vì vậy tôi không biết liệu đó có phải là cách để đi không ...
JHBonarius

@Brian Đó chắc chắn sẽ là một ý tưởng tồi ngay cả khi không được phép rõ ràng. Trong trường hợp này, chúng tôi chỉ xem xét liệu một nhà xây dựng được yêu cầu có được phép hỗ trợ các loại trình vòng lặp mà nó không bắt buộc phải hỗ trợ hay không. Trong trường hợp này, có yêu cầu "không tham gia" rõ ràng như được chỉ ra bởi Max, điều này chắc chắn sẽ không cho phép điều này. Nhưng thực sự không rõ "đủ điều kiện là một trình vòng lặp đầu vào" nghĩa là chính xác trong ngữ cảnh. Là cách không chính thức để thể hiện Cpp17InputIterator, hoặc nó cố gắng tham khảo các yêu cầu của ij? Tôi không biết.
eerorika

2
1) Trong C ++, chúng tôi đặt mức thấp tiêu chuẩn. . 2) Con constructor là các hàm thành viên không ảo . 3) Xem LWG 3297 ; tuy nhiên tôi không đặc biệt tin rằng chúng ta nên loại bỏ yêu cầu chuyển đổi ngầm định.
TC
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.