Tại sao std :: min chỉ hỗ trợ initializer_list?

Sep 24 2020

Chúng tôi có thể sử dụng std::mintheo cách dưới đây:

// 1.
int a = 1, b = 2;
std::min(a, b);

// 2.
std::min({1,2,3,4});

Nhưng tại sao không thể sử dụng std::vectorhoặc std::list, Bởi vì tham số trong mẫu là initializer_list.

template <class T, class Compare>
  pair<T,T> minmax (initializer_list<T> il, Compare comp);

Lý do cho thiết kế này là gì?

Trả lời

3 LouisGo Sep 25 2020 at 02:39

Để giải thích "tại sao nó không chấp nhận vùng chứa", hãy xem xét ngữ nghĩa:

std::min({ "foo", "bar", "hello" })

Ngữ nghĩa của std::min()có nghĩa là "tìm giá trị nhỏ nhất trong các tham số đầu vào". Do đó std::min()/ std::max()nhận hai đối số, hoặc một khởi tạo_list làm "nhiều đối số hơn".

std::min() không cung cấp khả năng "lặp qua vùng chứa", vì vùng chứa được coi là "tham số".

Để tìm giá trị tối thiểu trong một vùng chứa, có std::min_element(), và đề xuất của eerorika std::ranges::min()trong C ++ 20 sẽ tốt hơn.

Để std::min_element()sử dụng, bạn có thể tham khảo Làm cách nào để lấy giá trị tối đa (hoặc tối thiểu) trong một vectơ? .

3 JaMiT Sep 25 2020 at 03:01

"Họ càng suy nghĩ kỹ hệ thống ống nước, thì cống càng dễ tắc nghẽn." - Chỉ huy Montgomery Scott

Mục đích của std::minlà trả về các tham số nhỏ hơn của nó. Đơn giản và ngắn gọn. Cũng như với các thiết kế của riêng bạn, việc một chức năng (hoặc mẫu chức năng) làm tốt một việc sẽ tốt hơn là làm kém nhiều thứ. Vì vậy, std::minkhông có kiến ​​thức về container. Nó chỉ đơn giản là biết cách lấy hai thứ và so sánh chúng. Thay vào đó, kiến ​​thức về vùng chứa đã được cấp cho std::min_element. Giữa hai mẫu, hầu hết các trường hợp sử dụng đã được đề cập.

Một trường hợp không được đề cập là tìm tối thiểu nhiều hơn hai phần tử khi các phần tử đó không phải là phần tử của một (phạm vi trong a) vùng chứa. Trường hợp này có thể được xử lý bằng daisy-chaining std::min, nhưng hơi khó xử khi làm như vậy. Đối với C ++ 11, người ta đã quyết định rằng lợi ích của việc xử lý nhiều tham số hơn lớn hơn chi phí làm phức tạp mẫu, miễn là các biến chứng được giữ ở mức tối thiểu. Do đó, một cơ chế đơn giản để cung cấp một số lượng đối số tùy ý đã được chọn, cụ thể là std::initializer_list. Không cần cho phép các thùng chứa tùy tiện vì std::min_elementđã bao quát được tình huống đó.

3 eerorika Sep 25 2020 at 02:27

Nhưng tại sao không thể sử dụng std :: vector hoặc std :: list, Vì tham số trong mẫu là initializer_list.

Bởi vì không có quá tải sẽ chấp nhận một vectơ hoặc một danh sách. Đó không phải là danh sách khởi tạo.

Kể từ khi C ++ 20, bạn có thể sử dụng std::ranges::minmà bạn có thể chuyển một trong hai vùng chứa đó hoặc thực sự là bất kỳ phạm vi nào. Trước đó, std::min_elementnó hoạt động với bất kỳ cặp trình vòng lặp nào.