2016-05-23 16 views
5

Cách kinh điển để cập nhật giá trị (được gán một khóa và giá trị mới) bên trong boost::hana::map?Cách cập nhật/thay thế giá trị bản đồ trong `boost :: hana :: map`

tôi đã cố gắng sử dụng boost::hana::replace_if nhưng nó không hoạt động trên map vì nó không phải là một Functor - Tôi có thể lấy nó để làm việc bằng cách chuyển đổi các map đến một tuple và sau đó trở lại một map, nhưng nó có vẻ không hiệu quả.

Cách thay thế mà tôi hiện đang sử dụng đang gọi map::erase_key theo sau là map::insert.

Có chức năng nào replace hoặc update được thiết kế cho mục đích này mà tôi có thể bị thiếu không? Hay đây là cách cập nhật giá trị "kinh điển"?

Trả lời

4

Tôi không nghĩ rằng hiện tại có một cách kinh điển để thực hiện việc này. Nếu có trường hợp sử dụng hợp lệ cho điều này, có lẽ chúng ta có thể nhận được một chức năng trong đó để hỗ trợ nó. Vấn đề với hana::erase_key là bạn sẽ tạo một bản đồ mới và sau đó lại với hana::insert. Hiện tại, việc sử dụng hana::unpack và sau đó tạo bản đồ mới có lẽ là đặt cược tốt nhất của bạn.

#include <boost/hana.hpp> 

namespace hana = boost::hana; 

template <typename NewPair> 
struct replace_helper_t 
{ 
    NewPair const& new_pair; 

    template <typename Pair> 
    constexpr decltype(auto) operator()(Pair&& p) const 
    { 
    return hana::if_(
     hana::equal(hana::first(new_pair), hana::first(p)), 
     new_pair, 
     std::forward<Pair>(p) 
    ); 
    } 
}; 

struct replace_t 
{ 
    template <typename Map, typename NewPair> 
    constexpr auto operator()(Map&& m, NewPair&& new_pair) const 
    { 
    return hana::unpack(std::forward<Map>(m), 
     hana::on(
     hana::make_map, 
     replace_helper_t<NewPair>{std::forward<NewPair>(new_pair)} 
    ) 
    ); 
    } 
}; 

constexpr replace_t replace{}; 

int main() 
{ 
    auto my_map = hana::make_map(
    hana::make_pair(hana::int_c<7>, 7), 
    hana::make_pair(hana::int_c<13>, 13), 
    hana::make_pair(hana::int_c<23>, 23) 
); 

    auto new_map = replace(my_map, hana::make_pair(hana::int_c<13>, 14.0f)); 

    BOOST_HANA_RUNTIME_ASSERT(new_map == 
    hana::make_map(
     hana::make_pair(hana::int_c<7>, 7), 
     hana::make_pair(hana::int_c<13>, 14.0f), 
     hana::make_pair(hana::int_c<23>, 23) 
    ) 
); 
} 

Ghi chú khác, có lẽ hana::map phải là Functor.

+2

Tôi tin rằng bạn cần 'hana :: hash (hana :: first (new_pair)) == hana :: hash (hana :: first (p))' test là 'hana :: equal (hana :: đầu tiên (new_pair), hana :: đầu tiên (p)) '. Nếu không, nếu bạn thay thế giá trị được liên kết với khóa có mã băm va chạm với bất kỳ khóa nào khác trong bản đồ, bạn sẽ thay thế giá trị cho tất cả các khóa chia sẻ cùng một mã băm ngay cả khi các phím khác nhau. Về cơ bản bạn sẽ thay thế giá trị cho tất cả các khóa trong cùng một nhóm. Và một nitpick, nhưng việc sử dụng 'hana :: equal' có thể tốt hơn' == 'cho mã chung vì nó sẽ hoạt động với ví dụ. 'std :: integral_constant'. –

+1

Ah, đúng vậy. Tôi đã sửa ví dụ của mình và cũng đã thay đổi loại giá trị để chứng minh rằng nó không chỉ đơn giản là biến đổi giá trị. –

2

Bạn có cần thay đổi loại giá trị không? Nếu không, và nếu giá trị của bạn có thể được chỉ định, bạn có thể sử dụng map[key] = new_value hoặc tương đương hana::at_key(map, key) = new_value, vì hana::at_key trả về một tham chiếu.

Nếu bạn cần loại giá trị cần thay đổi, điều đó phức tạp hơn. Chúng tôi sẽ không thể thực hiện bất kỳ điều gì tại chỗ, vì loại bản đồ sau khi thay thế giá trị sẽ khác với loại của nó trước khi thay thế giá trị. Do đó, chúng ta phải tạo một bản đồ mới hoặc một số dạng xem sửa đổi của bản đồ đó (nhưng các khung nhìn hiện không được hỗ trợ). Sử dụng erase_keyinsert thực sự sẽ tạo ra hai bản đồ được tạo, không hiệu quả. Thay vào đó, chúng tôi có thể cung cấp một số chức năng update mà sẽ đạt được như nhau, nhưng sẽ chỉ tạo một bản sao của bản đồ (kết quả). Tôi tin rằng chúng tôi cũng có thể làm tốt hơn erase_key + insert về mặt thời gian biên dịch bằng cách cung cấp chức năng của riêng chúng tôi. Tôi đã mở this issue để theo dõi yêu cầu của bạn, vì tôi nghĩ điều quan trọng là cung cấp một cái gì đó như thế này; cảm ơn.

Cuối cùng, tôi muốn bình luận gì Jason nói:

Ngày lưu ý khác, có lẽ hana :: bản đồ phải là một functor.

hana::map có thể được thực hiện một Functor, nhưng tôi không chắc chắn rằng transform có thể chạm vào các phím của bản đồ trong khi vẫn tôn trọng luật Functor. Nếu không phải như vậy, bạn vẫn không thể nói "thay thế giá trị bằng XXX nếu khóa thỏa mãn một số biến vị ngữ" bằng cách sử dụng ví dụ: hana::replace_if. Tôi đã thử (nhưng thất bại cho đến nay) để tìm một ví dụ về các chức năng có thể phá vỡ luật nếu hana::transform về cơ bản đã chuyển đổi chuỗi các cặp khóa/giá trị cơ bản, nhưng trực giác của tôi là có thể tìm thấy ví dụ như vậy. Để được tiếp tục vấn đề # 278.

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