Tôi muốn sử dụng bộ nhớ cache, được thực hiện bởi số unordered_map
của boost, từ dynamic_bitset
đến dynamic_bitset
. Vấn đề, tất nhiên, là không có hàm băm mặc định từ bitet. Nó không có vẻ giống như một vấn đề khái niệm, nhưng tôi không biết làm thế nào để làm việc ra các technicalities. Tôi nên làm như thế nào?Bản đồ không có thứ tự (băm) từ bitet tới bitet khi tăng
Trả lời
Tôi tìm thấy một giải pháp bất ngờ. Nó chỉ ra tăng có một tùy chọn để #define BOOST_DYNAMIC_BITSET_DONT_USE_FRIENDS
. Khi điều này được xác định, các thành viên riêng bao gồm m_bits
trở thành công khai (tôi nghĩ rằng nó có để đối phó với trình biên dịch cũ hoặc một cái gì đó).
Vì vậy, bây giờ tôi có thể sử dụng @ câu trả lời KennyTM của, thay đổi một chút:
namespace boost {
template <typename B, typename A>
std::size_t hash_value(const boost::dynamic_bitset<B, A>& bs) {
return boost::hash_value(bs.m_bits);
}
}
Có to_block_range
chức năng các bản sao ra các từ mà bitet bao gồm trong một số bộ đệm. Để tránh sao chép thực tế, bạn có thể định nghĩa "trình lặp đầu ra" của riêng bạn mà chỉ xử lý các từ riêng lẻ và tính toán băm từ chúng. Re. cách tính băm: xem ví dụ hàm băm FNV.
Thật không may, thiết kế dynamic_bitset
là IMHO, braindead vì nó không cho phép bạn truy cập trực tiếp vào bộ đệm cơ bản (không phải là const
).
Có nên thực sự khó khăn khi sao chép-dán tập tin tiêu đề dynamic_bitset và thay thế nó bằng "my_dynamic_bitset", nơi mà tất cả sự khác biệt là nó không phải là riêng tư nữa? –
Đó là vấn đề bảo trì. Bạn phải lặp lại quy trình tương tự mỗi lần tệp chính được cập nhật vì bất kỳ lý do gì. – zvrba
Đây là số feature request.
Người ta có thể thực hiện một băm độc đáo không mấy hiệu quả bằng cách chuyển đổi các bitset để một vector tạm thời:
namespace boost {
template <typename B, typename A>
std::size_t hash_value(const boost::dynamic_bitset<B, A>& bs) {
std::vector<B, A> v;
boost::to_block_range(bs, std::back_inserter(v));
return boost::hash_value(v);
}
}
Làm cách nào để sử dụng? Tôi đã thử "unordered_map
@RS: http://www.ideone.com/c2CsK – kennytm
Chúng tôi không thể trực tiếp tính toán băm vì dữ liệu cơ bản trong dynamic_bitset
là tin (m_bits
)
Nhưng chúng ta có thể dễ dàng vượt qua quá khứ (lật đổ!) hệ thống đặc tả truy cập C++ mà không cần
- hack vào mã hoặc
- giả vờ trình biên dịch của bạn không phù hợp (
BOOST_DYNAMIC_BITSET_DONT_USE_FRIENDS
)
Điều quan trọng là mẫu chức năng to_block_range
mà là một friend
để dynamic_bitset
. Do đó, các chuyên ngành của chức năng này cũng có quyền truy cập vào dữ liệu cá nhân của nó (ví dụ: m_bits
).
Các mã kết quả không thể đơn giản hơn
namespace boost {
// specialise dynamic bitset for size_t& to return the hash of the underlying data
template <>
inline void
to_block_range(const dynamic_bitset<>& b, size_t& hash_result)
{
hash_result = boost::hash_value(bs.m_bits);
}
std::size_t hash_value(const boost::dynamic_bitset<B, A>& bs)
{
size_t hash_result;
to_block_range(bs, hash_result);
return hash_result;
}
}
Thật không may, điều này có vẻ không đúng. Chuyên môn cụ thể của hàm to_block_range là một người bạn của dynamic_bitset. Không thể có một hàm khác bằng cùng tên với các tham số khác nhau trong khi vẫn duy trì quyền truy cập của một hàm bạn bè. – BSchlinker
@BSchlinker Tôi không đồng ý: 'đẩy mạnh :: dynamic_bitset' được khai báo là: ' template
@BSchlinker: Các gốc _befriended_ mẫu chức năng là: 'template
các giải pháp đề xuất tạo ra băm cùng trong tình huống sau đây.
#define BOOST_DYNAMIC_BITSET_DONT_USE_FRIENDS
namespace boost {
template <typename B, typename A>
std::size_t hash_value(const boost::dynamic_bitset<B, A>& bs) {
return boost::hash_value(bs.m_bits);
}
}
boost::dynamic_biset<> test(1,false);
auto hash1 = boost::hash_value(test);
test.push_back(false);
auto hash2 = boost::hash_value(test);
// keep continue...
test.push_back(false);
auto hash31 = boost::hash_value(test);
// magically all hash1 to hash31 are the same!
giải pháp được đề xuất đôi khi không phù hợp với bản đồ băm.
Tôi đọc mã nguồn của dynamic_bitset tại sao điều này xảy ra và nhận ra rằng dynamic_bitset lưu trữ một bit cho mỗi giá trị giống như vector<bool>
. Ví dụ, bạn gọi dynamic_bitset<> test(1, false)
, sau đó dynamic_bitset ban đầu phân bổ 4 byte với tất cả số không và nó giữ kích thước của các bit (trong trường hợp này, kích thước là 1).Lưu ý rằng nếu kích thước của các bit lớn hơn 32, thì nó phân bổ 4 byte một lần nữa và đẩy nó trở lại vào dynamic_bitsets<>::m_bits
(vì vậy m_bits là một vectơ của 4 khối byte).
Nếu tôi gọi test.push_back(x)
, nó đặt bit thứ hai thành x và tăng kích thước bit thành 2. Nếu x
là sai, thì m_bits[0]
không thay đổi gì cả! Để tính toán băm chính xác, chúng ta cần lấy m_num_bits trong tính toán băm.
Sau đó, câu hỏi là như thế nào?
1: Sử dụng boost::hash_combine
Cách tiếp cận này đơn giản và dễ hiểu. Tôi không kiểm tra biên dịch này hay không.
namespace boost {
template <typename B, typename A>
std::size_t hash_value(const boost::dynamic_bitset<B, A>& bs) {
size_t tmp = 0;
boost::hash_combine(tmp,bs.m_num_bits);
boost::hash_combine(tmp,bs.m_bits);
return tmp;
}
}
2: flip m_num_bits% bits_per_block bit thứ. lật một chút dựa trên kích thước bit. Tôi tin rằng phương pháp này nhanh hơn 1.
namespace boost {
template <typename B, typename A>
std::size_t hash_value(const boost::dynamic_bitset<B, A>& bs) {
// you may need more sophisticated bit shift approach.
auto bit = 1u << (bs.m_num_bits % bs.bits_per_block);
auto return_val = boost::hash_value(bs.m_bits);
// sorry this was wrong
//return (return_val & bit) ? return_val | bit : return_val & (~bit);
return (return_val & bit) ? return_val & (~bit) : return_val | bit;
}
}
- 1. Làm thế nào để chuyển đổi chuỗi thành bitet?
- 2. Có phải sử dụng vectơ các giá trị boolean chậm hơn bitet động không?
- 3. Có thể chuyển đổi bitet <8> thành char in C++ không?
- 4. Làm thế nào tôi có thể chuyển đổi bitet thành ngắn trong c + +?
- 5. Hadoop - tăng nhiệm vụ bản đồ trong xml không tăng nhiệm vụ bản đồ khi chạy
- 6. Thực tế tăng cường - Lập bản đồ GPS tới OpenGL
- 7. Làm thế nào để thực hiện một bit bit (bitet) (trong Java)?
- 8. Thực hành được khuyến cáo cho thao tác bitet là gì?
- 9. Làm cách nào để chuyển đổi bitet thành mảng byte/uint8?
- 10. Bản đồ STL có luôn đặt cùng thứ tự khi lặp lại từ đầu() đến kết thúc() không?
- 11. C++ bản đồ băm riêng giữ gìn trật tự chèn
- 12. Bản đồ băm trong Python
- 13. thứ tự sắp xếp tăng :: weak_ptr sau khi hết hạn?
- 14. Đồ đạc Django có tải không đúng thứ tự khi thử nghiệm không?
- 15. Sắp xếp thứ tự trong bản đồ STL và đặt
- 16. Bản đồ F2 tới NEERDTreeToggle
- 17. bản đồ clojure theo thứ tự các cặp
- 18. bản đồ golang in ra theo thứ tự
- 19. Xây dựng một bản đồ có thứ tự với các bộ như phím
- 20. Bản đồ Google api có được Latitude và kinh độ từ tự động hoàn tất mà không có bản đồ
- 21. bản đồ cho băm trong Perl
- 22. Không tăng :: asio :: io_service bảo quản thứ tự xử lý?
- 23. Phần tử lược đồ tuần tự có đảm bảo thứ tự các phần tử con không?
- 24. Truyền an toàn cho bản đồ băm
- 25. Bản đồ màu trong đồ thị tăng cường breadth_first_visit
- 26. Cách tăng giá trị trong Bản đồ
- 27. Lập bản đồ java.long tới oracle.Number (14)
- 28. Con trỏ trỏ tới một bản đồ
- 29. Chuyển đổi một vector của bản đồ tới bản đồ bản đồ trong Clojure
- 30. CouchDB Bản đồ/Giảm tới một mảng
Xem https://svn.boost.org/trac/boost/ticket/2841. – kennytm
Tôi không thể sử dụng điều này vì m.bits là một thành viên riêng tư (đề xuất là thay đổi trong dynamic_bitset). –
m.bits phải là công khai const, đó là khá ngu ngốc! Bạn có thể lấy đi bằng cách sử dụng vector (là một bitet, nhưng một trong đó hoạt động tốt hơn) là chìa khóa? –