2013-11-24 22 views
16

Thư viện chuẩn triển khai std :: hash dưới dạng cấu trúc mẫu chuyên biệt cho các loại khác nhau. Nó được sử dụng như thế này:Tại sao std :: hash a struct thay vì một hàm?

#include <iostream> 
#include <functional> 

int main() 
{ 
    std::hash<int> hasher; 
    std::cout << hasher(1337) << std::endl; 

    return 0; 
} 

Câu hỏi của tôi là lý do đằng sau sự lựa chọn thiết kế này là gì. Tại sao nó không được thực hiện như một mẫu chức năng và sử dụng như thế này:

#include <iostream> 
#include <functional> 

int main() 
{ 
    std::cout << std::hash<int>(1337) << std::endl; 

    return 0; 
} 
+0

2 ví dụ giống hệt nhau, sự khác biệt duy nhất là đối tượng thứ hai không được đặt tên. – user2485710

+0

Các thùng chứa liên kết không có thứ tự có tham số kiểu mẫu để chỉ định băm; điều này cho phép sử dụng các đối tượng băm stateful (ví dụ: sử dụng một giá trị đặc biệt XORed trên băm). Việc loại chuyên môn về mẫu chức năng không có cú pháp tốt đẹp. – dyp

+1

@ user2485710 Ví dụ đầu tiên biên dịch, phần thứ hai thì không. Thứ hai sẽ cần phải được viết dưới dạng 'std :: hash () (1337)' để sử dụng cấu trúc tạm thời chưa được đặt tên. – hvd

Trả lời

16

Có, nhiều lý do, mỗi người tốt, đủ để chỉ lựa chọn:

  1. Bạn một phần có thể chuyên về các mẫu lớp học nhưng bạn chỉ có thể thực hiện đầy đủ các mẫu chức năng (ít nhất, cho đến nay). Do đó, bạn có thể cung cấp thay thế cho toàn bộ các đối số mẫu có liên quan với std::hash<T> làm mẫu lớp. Lưu ý rằng, quá tải một phần không giúp đỡ vì hàm băm cần được chỉ định bằng cách nào đó như một đối tượng không thể thực hiện với các hàm bị quá tải (trừ khi chúng được truy cập thông qua một đối tượng nhưng đó là những gì được phân biệt với).
  2. Các vùng chứa liên kết không theo thứ tự được tham số hóa với một thực thể tĩnh (cũng có thể được tùy chỉnh động nếu kiểu cụ thể hỗ trợ) được thực hiện dễ dàng hơn bằng cách sử dụng các mẫu lớp.
  3. Vì các thực thể được sử dụng cho hàm băm có thể tùy chỉnh, nên lựa chọn giữa việc sử dụng một loại hoặc một con trỏ hàm để tùy chỉnh. Các con trỏ hàm thường khó nội tuyến trong khi các hàm thành viên nội tuyến của một kiểu là tầm thường trong nội tuyến, cải thiện hiệu suất cho các hàm đơn giản như tính toán một hàm băm đơn giản một chút.
+3

Để công bằng, hàm băm mặc định có thể được gọi là hàm có thể cho các kiểu không được hỗ trợ, hãy thử gọi phương thức '.hash()', cho phép mọi thứ ở trên, cho phép băm adl (tốt hơn là buộc một 'std' injection) và cho phép các đối tượng tự' băm' nếu họ muốn. Nhưng điều đó vi phạm KISS, mặc dù nó khớp với cách hoạt động của 'less' và' begin'. – Yakk

4

Mẫu chức năng không thể được một phần đặc biệt với nhiều loại, trong khi std::hash chuyên với nhiều loại khác nhau như một lớp mẫu.

Và, theo cách lớp mẫu dựa này, bạn có thể làm một số chương trình meta như truy cập trở lại loại và loại chính như sau:

std::hash<X>::argument_type 
std::hash<X>::result_type 
Các vấn đề liên quan