2011-09-09 19 views
8

Tôi đã cố gắng tìm ra cách trả về một giá trị từ một bản đồ trong một phương thức const và tôi đã vấp vào phương thức at() cho bản đồ trong gcc 4.6.Là() const accessor cho tiêu chuẩn bản đồ trong C++ 11?

Khi tôi nhìn này lên, tôi nhận ra đó là phi tiêu chuẩn:

C++ map access discards qualifiers (const)

Nhưng nó chắc chắn là ít hơn một toàn bộ rất nhiều so với phương pháp tiết find(). Tôi đã tự hỏi nếu C + + 11 đã sửa chữa này - là at() cho một phần bản đồ của tiêu chuẩn mới?

Trả lời

17

Có. std::map có chức năng at thành viên trong C++ 11 với đặc điểm kỹ thuật sau đây (23.4.4.3/9):

T&  at(const key_type& x); 
const T& at(const key_type& x) const; 

Returns: Một tham chiếu tới mapped_type tương ứng với x trong *this.

Ném: Đối tượng ngoại lệ loại out_of_range nếu không có phần tử như vậy.

Độ phức tạp: lôgarit.

Lưu ý rằng chức năng thành viên này đã được thêm cụ thể vào std::map. Nó không được yêu cầu bởi yêu cầu tổng hợp container tổng hợp. Nếu bạn đang viết mã chung mà yêu cầu một số loại container kết hợp, bạn không thể sử dụng mới at này. Thay vào đó, bạn nên tiếp tục sử dụng find, mà là một phần của kết chứa khái niệm , hoặc viết riêng của bạn không thành viên helper:

template <typename AssociativeContainer> 
typename AssociativeContainer::mapped_type& 
get_mapped_value(AssociativeContainer&       container, 
       typename AssociativeContainer::key_type const& key) 
{ 
    typename AssociativeContainer::iterator it(container.find(key)); 
    return it != container.end() ? it->second : throw std::out_of_range("key"); 
} 

template <typename AssociativeContainer> 
typename AssociativeContainer::mapped_type const& 
get_mapped_value(AssociativeContainer const&     container, 
       typename AssociativeContainer::key_type const& key) 
{ 
    typename AssociativeContainer::const_iterator it(container.find(key)); 
    return it != container.end() ? it->second : throw std::out_of_range("key"); 
} 

Hoặc, nếu bạn có một thực hiện hỗ trợ tài liệu tham khảo rvalue và decltype, bạn không cần hai quá tải:

template <typename AssociativeContainer, typename Key> 
auto get_mapped_value(AssociativeContainer&& container, Key const& key) 
    -> decltype(std::declval<AssociativeContainer>().begin()->second)& 
{ 
    auto const it(container.find(key)); 
    return it != container.end() ? it->second : throw std::out_of_range("key"); 
} 

(Hoặc một cái gì đó gần đó; một điều thú vị về C++ 11 là không có hai trình biên dịch có các lỗi tương tự và tất cả dường như chấp nhận các tập con hơi khác nhau của lệ- - và không hợp lệ - mã C++ 11.)

+0

Tôi sẽ nói rằng tất cả các trình biên dịch được đóng trong C++ 11, nhưng đó có thể là tự lạc quan của tôi :) –

+1

[nitpick]. Phương thức 'at' không chỉ được thêm vào std :: map, mà còn cho std :: unordered_map. Đây là hai thùng chứa tiêu chuẩn duy nhất nó thực sự có ý nghĩa để có phương pháp này cho. Ngoài ra mã của bạn sẽ làm việc không chỉ cho AssociateveContainers, nhưng đối với UnorderedAssociateveContainers, ngoại trừ thiết lập và unordered_set và, một lần nữa, nó hầu như không có ý nghĩa đối với multimap và unordered_multimap. –

+0

@Konstantin: Có, có lẽ 'UniqueAssociativeContainer' sẽ là tên tốt hơn cho tham số mẫu (' UniqueAssociativeContainerOrUniqueUnorderedAssociativeContainer' hơi quá khó sử dụng: -O). Vấn đề là có các thùng chứa khác với các thùng chứa C++ Standard Library đáp ứng các yêu cầu của các khái niệm container và nên được hoán đổi cho nhau với các thùng chứa C++ Standard Library trong mã chung. Mã dựa trên 'mới' không thể sử dụng các thùng chứa khác. –

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