Đây là một câu hỏi khá phức tạp, và có thể là trường hợp VisualStudio là đúng và Comeau sai (điều này có vẻ thực sự khó tin).
Tiêu chuẩn nếu đọc từng chữ, xác định hàm tạo vector theo phương thức của hàm dựng sao chép (xem báo giá) và điều đó nghĩa là đối tượng thu được bằng dereferencing trình biến đổi trước tiên phải được chuyển đổi thành loại T và sau đó các nhà xây dựng bản sao nên được gọi. Tại thời điểm này, với một hàm tạo rõ ràng, mã không được biên dịch. Có vẻ như hợp lý để mong đợi một thực hiện, mặt khác, để trực tiếp gọi một nhà xây dựng lấy làm đối số các iterator dereferenced, trong trường hợp các cuộc gọi constructor sẽ được rõ ràng và do đó mã nên biên dịch.Điều này sẽ đi ngược lại từ ngữ chính xác trong báo giá bên dưới, vì hàm tạo bản sao được định nghĩa cho một kiểu T nhất định làm một hàm tạo lấy một tham chiếu duy nhất có thể liên quan đến một đối tượng kiểu T.
Tôi không thể nghĩ bất kỳ lý lẽ hợp lý nào không sử dụng cách tiếp cận Comeau, và tin của tôi (đây chỉ là ý kiến cá nhân) là từ ngữ trong tiêu chuẩn liên quan đến độ phức tạp của constructor vector có thể được phục hồi như yêu cầu chỉ N gọi tới T thích hợp constructor, khi thích hợp sẽ phải được định nghĩa là hàm tạo khớp với lệnh gọi T(*first)
(nghĩa là, hoặc là hàm tạo tham chiếu InputIterator::value_type
(theo giá trị hoặc có thể tham chiếu không đổi) hoặc bản sao T const ructor sau khi một chuyển đổi ngầm từ InputIterator::value_type
để T.
23.2.4.1 [lib.vector.cons]/1
phức tạp: Các nhà xây dựng mẫu vector (InputIterator đầu tiên, InputIterator cuối cùng) làm chỉ N các cuộc gọi đến nhà xây dựng bản sao của T (trong đó N là khoảng cách giữa đầu tiên và cuối cùng) và không có phân bổ lại nếu trình lặp đầu tiên và cuối cùng là các loại truy cập về phía trước, hai chiều hoặc ngẫu nhiên . Nó làm cho các lệnh gọi N tới hàm tạo bản sao của T và nhật ký thứ tự N phân bổ lại nếu chúng là chỉ các trình lặp đầu vào.
Tôi muốn biết làm thế nào trình biên dịch VS cư xử khi đưa ra:
struct T1;
struct T2 {
operator T1();
};
struct T1 {
T1(T2 const &) { std::cout << "T1(T2)" << std::endl; }
};
T2::operator T1() {
std::cout << "T2::operator T1" << std::endl;
return T1(*this);
}
int main() {
std::vector<T2> v2;
v2.push_back(T2());
std::vector<T1> v1(v2.begin(), v2.end());
}
Với g ++ kết quả là T2::operator T1
không được gọi, mà đúng hơn là các yếu tố trong v1
được xây dựng trực tiếp từ các yếu tố trong v2
. Tôi sẽ giả định rằng với VS trình biên dịch sẽ sử dụng T2::operator T1
để chuyển đổi từ mỗi phần tử trong v2
thành phần tử T1 và sau đó gọi hàm tạo bản sao. Là vậy sao?
Nguồn
2010-01-05 01:57:33
Trả lời gián tiếp tại đây: http://stackoverflow.com/questions/1943228/implicit-constructor-conversion-works-on-explicit-vectorvector-only-sometimes –
Tôi vừa viết câu trả lời ở đây dựa trên câu hỏi đó + câu trả lời, nhưng nó thực sự không áp dụng, vì 'std :: vector :: iterator' không phải là một kiểu không thể tách rời, và fill-constructor không được gọi. Vì vậy, tôi đã xóa nó. Tôi nghĩ rằng tất cả những gì tôi có thể nói là tiêu chuẩn không * cấm * chuyển đổi rõ ràng trong bất kỳ nhà xây dựng vùng chứa nào. –
Potatoswatter
VS 2010 Beta hoạt động như Comeau và gcc. –