“Sử dụng ODR” có nghĩa là gì?


92

Điều này chỉ xuất hiện trong bối cảnh của một câu hỏi khác .

Rõ ràng các hàm thành viên trong các mẫu lớp chỉ được khởi tạo nếu chúng được sử dụng ODR. Ai đó có thể giải thích chính xác điều đó có nghĩa là gì. Các bài viết trên wikipedia Một Definition Rule (ODR) không đề cập đến " ODR sử dụng ".

Tuy nhiên, tiêu chuẩn xác định nó là

Một biến có tên xuất hiện dưới dạng biểu thức được đánh giá tiềm năng được sử dụng odr trừ khi nó là một đối tượng đáp ứng các yêu cầu để xuất hiện trong một biểu thức hằng số (5.19) và việc chuyển đổi giá trị thành giá trị (4.1) được áp dụng ngay lập tức.

trong [basic.def.odr].

Chỉnh sửa: Rõ ràng đây là phần sai và toàn bộ đoạn văn có nhiều định nghĩa cho những thứ khác nhau. Đây có thể là cái có liên quan cho chức năng thành viên mẫu lớp:

Một hàm không quá tải có tên xuất hiện dưới dạng một biểu thức được đánh giá tiềm năng hoặc một thành viên của một tập hợp các hàm ứng cử viên, nếu được chọn theo độ phân giải quá tải khi được tham chiếu từ một biểu thức được đánh giá tiềm năng, được sử dụng odr, trừ khi nó là một ảo thuần túy chức năng và tên của nó không đủ điều kiện rõ ràng.

Tuy nhiên, tôi không hiểu, quy tắc này hoạt động như thế nào trên nhiều đơn vị biên dịch? Tất cả các hàm thành viên có được khởi tạo không nếu tôi khởi tạo một cách rõ ràng một mẫu lớp?


2
Lưu ý rằng [basic.def.odr] / 6 áp dụng cho các hàm thành viên của mẫu lớp "Có thể có nhiều hơn một định nghĩa [...]"
dyp

3
"Tất cả các hàm thành viên có được khởi tạo không nếu tôi khởi tạo một cách rõ ràng một mẫu lớp?" Có, xem [temp.explicit] / 8 + 9
dyp

Câu trả lời:


71

Nó chỉ là một định nghĩa tùy ý, được tiêu chuẩn sử dụng để chỉ định khi nào bạn phải cung cấp định nghĩa cho một thực thể (trái ngược với chỉ một khai báo). Tiêu chuẩn không chỉ nói "đã qua sử dụng", vì điều này có thể được hiểu đa dạng tùy thuộc vào ngữ cảnh. Và một số việc sử dụng ODR không thực sự tương ứng với những gì người ta thường kết hợp với "sử dụng"; ví dụ, một hàm ảo luôn được sử dụng ODR trừ khi nó thuần túy, ngay cả khi nó thực sự không được gọi ở bất kỳ đâu trong chương trình.

Định nghĩa đầy đủ nằm trong §3.2 , đoạn thứ hai, mặc dù điều này chứa các tham chiếu đến các phần khác để hoàn thành định nghĩa.

Liên quan đến các mẫu, ODR được sử dụng chỉ là một phần của câu hỏi; phần khác là khởi tạo. Đặc biệt, §14.7 bao gồm khi một mẫu được khởi tạo. Nhưng cả hai có liên quan với nhau: trong khi văn bản trong §14.7.1 (diễn giải ngầm) khá dài, nguyên tắc cơ bản là một mẫu sẽ chỉ được khởi tạo nếu nó được sử dụng và trong ngữ cảnh này, được sử dụng có nghĩa là được sử dụng ODR. Do đó, một hàm thành viên của mẫu lớp sẽ chỉ được khởi tạo nếu nó được gọi, hoặc nếu nó là ảo và bản thân lớp được khởi tạo. Bản thân tiêu chuẩn dựa vào điều này ở nhiều nơi: việc std::list<>::sortsử dụng <trên các phần tử riêng lẻ, nhưng bạn có thể tạo danh sách trên một loại phần tử không hỗ trợ <, miễn là bạn không gọi sortnó.


có thể sử dụng ODR có chồng chéo với "thời gian tạm thời cụ thể hóa" không?
v.oddou

23

Nói một cách đơn giản, odr-used có nghĩa là một cái gì đó (biến hoặc hàm) được sử dụng trong ngữ cảnh mà định nghĩa của nó phải có mặt.

ví dụ,

struct F {
   static const int g_x = 2;
};

int g_x_plus_1 = F::g_x + 1; // in this context, only the value of g_x is needed.
                             // so it's OK without the definition of g_x

vector<int>  vi;
vi.push_back( F::g_x );      // Error, this is odr-used, push_back(const int & t) expect
                             // a const lvalue, so it's definition must be present

Lưu ý, push_back ở trên được thông qua trong MSVC 2013, hành vi này không tuân thủ tiêu chuẩn, cả gcc 4.8.2 và clang 3.8.0 đều không thành công, thông báo lỗi là: tham chiếu không xác định đến `K :: g_x '


Có thể odr-sử dụng một thành viên dữ liệu tĩnh như vi.push_back( F::g_x );trong c ++ không?
Rankaba

Nhưng một rvalue cũng có thể được chuyển đến const int&?
scottxiao 19/02/18

8
+1 cho câu mở đầu ngắn gọn: "Nói một cách đơn giản, odr-used có nghĩa là một cái gì đó (biến hoặc hàm) được sử dụng trong ngữ cảnh mà định nghĩa của nó phải có mặt."
Paul Masri-Stone

1
Tôi không hiểu cách bạn biên dịch mã đó. Họ có trong cùng một TU không ?. Nếu có thì F :: g_x đã được định nghĩa trước đó rồi push_back, tất nhiên nó sẽ vượt qua. Phải không?
Lewis Chan

1
@bigxiao " một rvalue cũng có thể được chuyển " Có và một đối tượng tạm thời được tạo bởi trình biên dịch và tham chiếu liên kết với đối tượng đó. OTOH khi truyền giá trị có nghĩa là chuyển đối tượng đó được tham chiếu bởi đánh giá của giá trị: khi bạn truyền giá trị, bạn có thể mong đợi tham số trong hàm tham chiếu đến đối tượng chính xác. Trình biên dịch sẽ không tạo tạm thời. Nếu bạn muốn tạm thời, hãy tạo một cái với operator+.
tò mò
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.