2010-06-01 27 views
26

Các nhà xây dựng của variadic có phải ẩn các trình tạo ngầm được tạo ra không, tức là hàm tạo mặc định và hàm tạo bản sao?Các nhà xây dựng variadic có phải che giấu những người tạo ra ngầm không?

struct Foo 
{ 
    template<typename... Args> Foo(Args&&... x) 
    { 
     std::cout << "inside the variadic constructor\n"; 
    } 
}; 

int main() 
{ 
    Foo a; 
    Foo b(a); 
} 

Bằng cách nào đó tôi đã mong đợi này để in gì sau khi đọc this answer, nhưng nó in inside the variadic constructor hai lần trên g ++ 4.5.0 :(Có hành vi này đúng


Nó cũng xảy ra mà không mẫu variadic:

struct Foo 
{ 
    Foo() 
    { 
     std::cout << "inside the nullary constructor\n"; 
    } 

    template<typename A> Foo(A&& x) 
    { 
     std::cout << "inside the unary constructor\n"; 
    } 
}; 

int main() 
{ 
    Foo a; 
    Foo b(a); 
} 

Một lần nữa, cả hai dòng được in.

+1

Tôi vừa chạy thử nghiệm nhanh trên gcc45 và một hàm tạo mẫu không thường xuyên, không biến đổi sẽ ngăn việc tạo trình biên dịch tạo ra hàm tạo mặc định. Nghi ngờ của tôi là các quy tắc đã thay đổi trong C++ 0x. –

+2

@ Dennis: Tôi sẽ được _really_ ngạc nhiên nếu C++ 0x sẽ thay đổi các quy tắc sẽ được giới thiệu với C++ 0x. ':)' – sbi

+0

@Dennis Vậy là câu trả lời có liên quan không? Nó nói "một nhà xây dựng mẫu hoặc nhà điều hành gán sẽ không ngăn chặn trình biên dịch tạo ra một". – fredoverflow

Trả lời

19

Tuyên bố của constructor sao chép ngầm được tuyên bố không, trên thực tế, bị đàn áp. Nó chỉ không được gọi là do các quy tắc của độ phân giải quá tải.

Trình tạo bản sao ngầm được khai báo ngầm có dạng Foo(const Foo&). Phần quan trọng của điều này là nó lấy một tham chiếu const. Mẫu hàm tạo của bạn lấy tham chiếu không phải const.

a không phải là const, do đó mẫu trình xây dựng do người dùng khai báo không phải const được ưu tiên hơn hàm tạo bản sao được khai báo ngầm. Để gọi constructor sao chép ngầm-tuyên bố, bạn có thể làm a const:

const Foo a; 
Foo b(a); 

hoặc bạn có thể sử dụng static_cast để có được một tham chiếu const để a:

quy tắc giải quyết
Foo a; 
Foo b(static_cast<const Foo&>(a)); 

Các quá tải mà mô tả này là tìm thấy chủ yếu trong §13.3.3.2/3 của C++ 0x FCD. Kịch bản đặc biệt này, với sự kết hợp của giá trị trái và rvalue tài liệu tham khảo, được loại được mô tả bởi các ví dụ khác nhau trên trang 303.


Mẫu constructor variadic sẽ ngăn chặn các nhà xây dựng mặc định ngầm tuyên bố vì một mẫu constructor variadic là người sử dụng -declared và các nhà xây dựng mặc định ngầm tuyên bố chỉ được cung cấp nếu không có sử dụng tuyên bố constructors (C++ 0x FCD §12.1/5):

Nếu không có nhà xây dựng sử dụng kê khai lớp X, một constructor không có tham số nào được khai báo ngầm định là defaulted.

Một constructor mẫu variadic sẽ không ngăn chặn các nhà xây dựng bản sao ngầm tuyên bố bởi vì chỉ có một tổ chức phi-mẫu nhà xây dựng có thể là một nhà xây dựng bản sao (C++ 0x FCD §12.8/2, 3 và 8):

một phi mẫu constructor cho lớp X là một constructor sao chép nếu tham số fi đầu tiên của nó là loại X&, const X&, volatile X& hoặc const volatile X&, và một trong hai không có các thông số khác hoặc nếu không tất cả các thông số khác có đối số mặc định.

Một phi mẫu constructor cho lớp X là một constructor chuyển nếu tham số fi đầu tiên của nó là loại X&&, const X&&, volatile X&&, hoặc const volatile X&&, và một trong hai không có các thông số khác hoặc nếu không tất cả các thông số khác có đối số mặc định.

Nếu xác định lớp không tuyên bố rõ ràng một hàm tạo bản sao và không có hàm tạo di chuyển do người dùng khai báo, thì hàm tạo bản sao được ngầm khai báo là mặc định.

+0

@James "một hàm tạo mẫu [...] không bao giờ là một hàm tạo bản sao" -> vì vậy g ++ 4.5.0 là lỗi và dòng thứ hai không được in bất kỳ thứ gì? Và bởi FCD bạn có nghĩa là n3090? – fredoverflow

+0

@Fred: FCD là n3092; Tôi đã phải cập nhật các dấu ngoặc kép vì tôi đã mở n3035 vì lý do nào đó và có một số thay đổi trong n3092 ... xin lỗi về điều đó. –

+0

@James Điều đó cũng xảy ra với các mẫu không phải là biến thể, tôi đã cập nhật câu hỏi của mình! – fredoverflow

Các vấn đề liên quan