hiểu biết của tôi về C++ ngầm constructor sao chép tương tự nhưlý do đằng sau C++ ngầm sao chép và di chuyển constructor?
T(T const& x) :
base1(x), base2(x) ... ,
var1(x.var1), var2(x.var2)...
{}
Move constructor, sao chép & phân di chuyển cũng theo mô hình tương tự.
Tại sao nó không được xác định tương tự như sau?
T(T const& x) :
base1(static_cast<base1 const&>(x)),
base2(static_cast<base2 const&>(x)) ... ,
var1(x.var1), var2(x.var2)...
{}
Ví dụ
Tôi đã có một lớp mà có sao chép/di chuyển hành constructor/chuyển nhượng ngầm, cũng như một số nhà xây dựng chuyển đổi. Tôi đã được giao công việc cho một số lớp thực hiện.
class common_work //common implementation of many work like classes
{
common_work(common_work const&) = default;
common_work(common_work&&) = default;// ... implicit constructors work for me.
//a forwarding constructor which can take many work like objects
template<class T, enable_if<work_like<T> > >
common_work(T&& x) { ... }
};
class work1 //one of the implementation
{
work1(work1 const&) = default;
work1(work1&&) = default; ...
common_work impl_;
};
Đây là tốt, như work1
sao chép/di chuyển nhà xây dựng đã kêu gọi constructor sao chép/di chuyển cho common_work
, và chuyển tiếp constructor được sử dụng bởi nhà thầu khác [không được hiển thị trong code] mà chuyển đổi từ một loại work
.
Sau đó, tôi nghĩ rằng để kế thừa work1
từ common_work
cho EBO và các lý do khác. Vì vậy, các lớp mới work1
trông giống như
class work1 : private common_work
{
work1(work1 const&) = default;
work1(work1&&) = default; ...
};
Nhưng, work1
là một lớp work_like
, đột nhiên các nhà xây dựng chuyển tiếp đã nhận được một trận đấu tốt hơn, như các nhà xây dựng sao chép/di chuyển cho common_work
đòi hỏi một static_cast
từ nguồn gốc đến cơ sở.
LƯU Ý:
- Có một loại tương tự của các ví dụ được đưa ra bởi Scott Meyers, nơi xây dựng bản sao gây nên chuyển tiếp constructor như constructor sao chép đòi hỏi một bổ sung const, trong khi chuyển tiếp constructor đòi hỏi gì. Nhưng tôi nghĩ, vấn đề đó phát sinh do thiết kế lớp sai, trong khi vấn đề ở đây là do đối số được chuyển đến lớp cơ sở trong khi sao chép/di chuyển ngầm không chính xác.
- Tôi không thể viết một công cụ chuyển tiếp/gán nhiệm vụ chuyển tiếp phổ biến và xóa các hàm ẩn, vì các hàm bị xóa cũng tham gia vào quá trình phân giải quá tải và gây ra lỗi nếu khớp chính xác.
- Giải pháp hiện tại tôi có là để làm cho
common_work
làm CRTP, tức là loại lớp dẫn xuất được chuyển làm đối số mẫu và trong bộ xây dựng chuyển tiếp lọc nó ra làenable_if<and_<work_like<T>,not_<is_same<T,Derived> > > >
. Nếu không, tôi phải viết thủ công hàm sao chép/di chuyển/gán chowork1
vàstatic_cast
đến các lớp cơ sở một cách rõ ràng, đó là lỗi, dễ bị lỗi và bảo trì.
Có lẽ bạn có thể giải quyết vấn đề này bằng cách tăng cường ràng buộc SFINAE để từ chối 'T' có nguồn gốc từ 'common_work'? –
Đó là những gì tôi làm hiện nay. Nhìn vào điểm thứ ba trên phần LƯU Ý. Mặc dù, nó không được là 'is_same', thay vì 'is_same , có nguồn gốc>' –
abir
OK, xin lỗi. Tôi không đọc ghi chú cuối cùng :) –