Câu trả lời đúng là Jonathan Wakeley. Tôi sẽ để điều này vì nó cung cấp thông tin hữu ích cho những người có vấn đề tương tự liên quan đến insert
.
Phiên bản ngắn gọn là do sự cố trong triển khai Thư viện chuẩn được sử dụng bởi GCC 4.7.2, dẫn đến từ ngữ gây hiểu lầm được sử dụng trong tiêu chuẩn C++ 11. Có một đề xuất thay đổi cho các từ ngữ, cũng như một sửa chữa của việc thực hiện trong GCC 4.8.
Long phiên bản
This GCC bug entry báo cáo một vấn đề rất tương tự, nơi insert
được sử dụng thay vì emplace
. Các libstdC++ thực hiện insert
theo tiêu chuẩn, trong đó nêu về insert
chức năng (cụ thể là, template <class P> pair<iterator,bool> insert(P&& obj)
):
(§23.5.4.4/5) Ghi chú: chữ ký này sẽ không tham gia vào giải quyết tình trạng quá tải nếu P là ngầm mui trần đến value_type
.
libstdC++ dường như đã thực hiện yêu cầu này bằng cách sử dụng câu hỏi enable_if
kiểm tra std::is_convertible<>
cho các loại có liên quan.
Báo cáo lỗi được liên kết ở trên các trạng thái sau đó thực sự cần sử dụng std::is_constructible<>
và phải thay đổi từ ngữ trong tiêu chuẩn. Nó liên kết đến một vấn đề LWG (nhóm công tác ngôn ngữ), trong đó đề xuất một sự thay đổi tiêu chuẩn cho điều này đã (LWG issue #2005, xem Portland 2012 nhập cảnh, phần liên quan của sự thay đổi đề xuất dưới đây):
Thay đổi 23.5.4.4 [unord.map.modifers] xung quanh p. 1 như được chỉ ra:
template <class P>
pair<iterator, bool> insert(P&& obj);
[...] Ghi chú: chữ ký này sẽ không tham gia vào giải quyết tình trạng quá tải nếu P là
ngầm mui trần để VALUE_TYPE
std::is_constructible<value_type, P&&>::value
là đúng.
Sự thay đổi đề xuất cũng khẳng định rằng tác động của các insert
chức năng mô tả ở trên nên được tương đương với của emplace(std::forward<P>(obj))
. Do đó, có thể nói rằng vấn đề được mô tả trong câu hỏi của bạn chính xác là cùng một vấn đề.
Và quả thực, những thay đổi đề xuất dường như được phản ánh trong gần đây GCC 4.8 snapshot: Khi bạn biên dịch mã của bạn với GCC 4.8, việc kiểm tra is_convertible
không được thực hiện và không có thông báo lỗi xuất hiện.
Đóng, nhưng không có xì gà :) LWG 2005 chỉ áp dụng cho 'chèn' không' emplace', lý do chương trình không thành công với GCC 4.7.2 là nó không kiểm tra quyền truy cập như một phần của trích dẫn đối số mẫu (như được yêu cầu trong C++ 03), do đó 'is_constructible' bị lỗi truy cập do hàm tạo riêng. GCC 4.8 thực hiện quy tắc C++ 11 và kiểm tra truy cập trong quá trình trích đối số mẫu –
Bạn có thể xác nhận sự khác biệt không phải do bất kỳ thay đổi nào trong thư viện chuẩn bằng cách xử lý trước mã bằng G ++ 4.7 (vì vậy nó sử dụng thư viện từ 4.7) rồi compilng với 4.8, trong trường hợp đó chương trình hoạt động, chứng minh nó là trình biên dịch không phải thư viện đã thay đổi –