2016-03-25 21 views
6

Giả sử bạn có các lớp sau:Tại sao không thể khởi tạo cặp với hàm tạo bản sao "non const" trong khi nó có thể khởi tạo một cặp mà không có?

struct A { 
    A() {} 
    A (A &) = delete; 
}; 

int main() { 
    std::pair<A, int> p1; 
    return 0; 
} 

Đoạn mã dưới đây sẽ thất bại để biên dịch (sử dụng -std=c++11 với g++) với các lỗi sau:

/usr/include/c++/5/bits/stl_pair.h: In instantiation of ‘struct std::pair’:

test.cpp:13:23: required from here

/usr/include/c++/5/bits/stl_pair.h:127:17: error: ‘constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = A; _T2 = int]’ declared to take const reference, but implicit declaration would take non-const

constexpr pair(const pair&) = default; 

Theo thông báo lỗi, tôi sẽ giả định rằng điều này là do không thể instanciate constructor sao chép mặc định vì vòng loại const trên đối số std::pair.

Tôi có thể hiểu lý do tại sao điều này sẽ không biên dịch mà không có = delete, bởi vì nó không thể instanciate các nhà xây dựng bản sao có một tham số std::pair const&.

Nhưng với = delete, tôi hy vọng trình biên dịch sẽ không khởi tạo trình xây dựng như vậy vì nó không thể (theo như tôi hiểu). Trên thực tế, nhà xây dựng bản sao này sẽ bị xóa như thể hiện bởi đoạn mã này:

std::pair<A, int> p1; 
decltype(p1) p2(p1); 

Những thất bại:

test.cpp:11:23: error: use of deleted function ‘constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = A; _T2 = int]’

decltype(p1) p2(p1); 

Về cơ bản, câu hỏi của tôi là: Tại sao các trình biên dịch thất bại trong việc tạo một constructor sao chép xóa của std::pair?

+0

Xem http://cplusplus.github.io/LWG/lwg-closed.html#2068 –

Trả lời

5

[class.copy]/8:

The implicitly-declared copy constructor for a class X will have the form

X::X(const X&) 

if each potentially constructed subobject of a class type M (or array thereof) has a copy constructor whose first parameter is of type const M& or const volatile M& . Otherwise, the implicitly-declared copy constructor will have the form

X::X(X&) 

Do đó, nếu các nhà xây dựng bản sao của std::pair<A, int> đã được khai báo ngầm, nó sẽ có dạng pair::pair(pair &).

[dcl.fct.def.default]/1:

A function that is explicitly defaulted shall

  • be a special member function,

  • have the same declared function type (except for possibly differing ref-qualifiers and except that in the case of a copy constructor or copy assignment operator, the parameter type may be “reference to non-const T ”, where T is the name of the member function's class) as if it had been implicitly declared, and

  • not have default arguments.

Kể từ khi tuyên bố pair(const pair&) = default; không có cùng tuyên bố loại chức năng như các nhà xây dựng bản sao mà có thể đã được tuyên bố ngầm, và không ngoại lệ áp dụng, chương trình là vô hình thành.

6

Nếu bạn muốn = delete trình tạo bản sao, biểu mẫu thích hợp là: A(const A&) = delete;. Xem cách bạn quên rằng const? pair có thể được sử dụng với loại không thể sao chép, thậm chí là loại không thể di chuyển được.

vấn đề instantiation của bạn cũng có thể được chứng minh với:

struct A { 
    A(A&) = delete; 
}; 

struct B : A { 
    B(const B&) = default; 
}; 

hoặc ...

struct B { 
    B(const B&) = default; 
    A a; 
}; 

Về cơ bản, pair= default sao chép ctor của nó, và định nghĩa nó như tham gia một const pair&, nhưng một một trong số các loại của bạn xác định nó để có một không const &, do đó, thế hệ mặc định không thành công vì nó không thể vượt qua nó const & của bạn không const &. Mặc dù của bạn là = delete ed, nó không quan trọng, nó không nhận được rằng đến nay.

Một bản sao ctor bản sao mặc định sẽ bị xóa nếu một thành viên hoặc lớp cơ sở không thể sao chép được. Nhưng để tìm ra điều đó, nó phải có một chức năng mà nó có thể gọi (ngay cả khi chức năng đó bị xóa). Trong những trường hợp này, nó không thể vượt qua một const & đến một không const & do đó, nó thậm chí không thể tìm ra rằng bạn có một ctor sao chép đã xóa. Conceivably, một cái gì đó trong tiêu chuẩn có thể được viết để phù hợp với trường hợp này cạnh.

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