Gần đây tôi đã gặp phải sự cố trong khi cố gắng triển khai phân cấp lớp với các trình xây dựng chuyển tiếp hoàn hảo. Hãy xem xét ví dụ sau:Xung đột giữa hàm tạo chuyển tiếp hoàn hảo và hàm tạo bản sao trong phân cấp lớp
struct TestBase {
template<typename T>
explicit TestBase(T&& t) : s(std::forward<T>(t)) {} // Compiler refers to this line in the error message
TestBase(const TestBase& other) : s(other.s) {}
std::string s;
};
struct Test : public TestBase {
template<typename T>
explicit Test(T&& t) : TestBase(std::forward<T>(t)) {}
Test(const Test& other) : TestBase(other) {}
};
Khi tôi cố gắng để biên dịch mã tôi nhận được lỗi sau:
Error 3 error C2664: 'std::basic_string<_Elem,_Traits,_Alloc>::basic_string(const std::basic_string<_Elem,_Traits,_Alloc> &)' : cannot convert parameter 1 from 'const Test' to 'const std::basic_string<_Elem,_Traits,_Alloc> &'
sự hiểu biết của tôi là trình biên dịch xử lý các nhà xây dựng chuyển tiếp hoàn hảo như một toán tốt hơn so với copy constructor. Xem ví dụ Scott Meyers: Copying Constructors in C++11. Trong các triển khai khác mà không có phân cấp lớp, tôi có thể vô hiệu hóa trình xây dựng chuyển tiếp hoàn hảo từ một trình tạo bản sao thông qua SFINAE. Xem ví dụ Martinho Fernandes: Some pitfalls with forwarding constructors. Khi tôi cố gắng áp dụng giải pháp đã đề cập cho ví dụ này, tôi vẫn không thể biên dịch với cùng một thông báo lỗi.
Tôi nghĩ một giải pháp có thể là tránh chuyển tiếp hoàn hảo, lấy các tham số theo giá trị trong các hàm tạo và di chuyển từ chúng sang các biến lớp.
Vì vậy, câu hỏi của tôi là nếu có một số giải pháp khác cho vấn đề này hoặc nếu chuyển tiếp hoàn hảo không thể trong trường hợp này?
Cập nhật: Hóa ra câu hỏi của tôi dễ hiểu. Vì vậy, tôi sẽ cố gắng làm sáng tỏ ý định của mình và bối cảnh một chút.
- Mã hoàn tất như được đăng trong câu hỏi. Không có đối tượng nào khác được tạo hoặc hàm được gọi. Lỗi xuất hiện trong khi cố gắng biên dịch ví dụ đã đăng.
- Mục đích của việc tạo hàm tạo chuyển tiếp hoàn hảo là khởi tạo thành viên và không phải để có một số loại hàm tạo bản sao phụ. Lý do ở đây là để lưu một số bản sao đối tượng khi khởi tạo các thành viên với các đối tượng tạm thời (như được đề xuất trong các cuộc đàm phán của Scott Meyers)
- Thật không may là nó đã trở thành nhà xây dựng chuyển tiếp hoàn hảo có thể xung đột với các nhà xây dựng quá tải khác (trong ví dụ này với các nhà xây dựng sao chép) .
- Giống như các câu trả lời và nhận xét cho câu hỏi này được đề xuất: Các giải pháp có thể có ở đây là giới thiệu các công thức rõ ràng hoặc có các nhà xây dựng không có quy trình riêng (ví dụ: về ví dụ có hai hàm tạo với tham số
const string&
vàstring&&
tương ứng).
nó Có thể mà bạn đã viết một cái gì đó như 'std :: string (thử nghiệm)' thay vì 'std :: string (test.s) '? Vui lòng chỉ cho chúng tôi dòng 130 của main.cc – Andrey
Bạn đã viết 's (std :: forward (t))' thay vì 's (std :: forward (t) .s)'. –
avakar
Nói chung là một ý tưởng tồi để trộn lẫn quá tải và mẫu chuyển tiếp. Tôi muốn tạo một constructor đơn từ 'string' và thêm một mẫu' make_test' * function * chuyển tiếp. –