2013-05-26 32 views
13

Tôi đã nhìn vào std :: unordered_map và thấy rằng nếu tôi muốn sử dụng một chuỗi như là chìa khóa, tôi sẽ phải tạo một lớp có chứa một functor.Có thể sử dụng hàm lambda cho tham số mẫu không?

Ngoài sự tò mò, tôi đã tự hỏi liệu một lambda có thể được sử dụng thay cho điều này không.

Dưới đây là bản gốc làm việc:

struct hf 
{ 
    size_t operator()(string const& key) const 
    { 
    return key[0]; // some bogus simplistic hash. :) 
    } 
} 

std::unordered_map<string const, int, hf> m = {{ "a", 1 }}; 

Đây là nỗ lực của tôi:

std::unordered_map<string const, int, [](string const& key) ->size_t {return key[0];}> m = {{ "a", 1 }}; 

Đó thất bại với các lỗi sau đây:

exec.cpp: In lambda function: 
exec.cpp:44:77: error: ‘key’ cannot appear in a constant-expression 
exec.cpp:44:82: error: an array reference cannot appear in a constant-expression 
exec.cpp: At global scope: 
exec.cpp:44:86: error: template argument 3 is invalid 
exec.cpp:44:90: error: invalid type in declaration before ‘=’ token 
exec.cpp:44:102: error: braces around scalar initializer for type ‘int’ 

Với lỗi, nó sẽ có vẻ rằng Lamba là đủ khác nhau từ một functor rằng nó làm cho nó không phải là một biểu hiện liên tục. Đúng không?

+2

'std :: hash' là chuyên biệt cho' std :: string', không cần phải cung cấp một cái gì đó cho mình nếu bạn không muốn cải thiện/thay đổi băm. Ngoài ra, hãy suy nghĩ về những gì bạn đang làm: 'std :: unordered_map' mong đợi một * type * làm đối số mẫu và biểu thức lambda chính xác là - biểu thức, nghĩa là giá trị, * not * a type. – Xeo

+0

Tôi thấy rằng trong trình biên dịch g ++ tôi đã sử dụng (v4.5.3 với -std = gnu ++ 0x), nó sẽ cho tôi một loạt các lỗi nếu tôi không chỉ định hàm băm khi sử dụng một khóa chuỗi. – Adrian

+0

Đối với nó là một biểu hiện, vâng, tôi đoán đó sẽ là câu trả lời. – Adrian

Trả lời

12

Cách để vượt qua chức năng lambda là:

auto hf = [](string const& key)->size_t { return key[0]; }; 

unordered_map<string const, int, decltype(hf)> m (1, hf); 
           ^^^^^^^^^^^^  ^^ 
           passing type  object 

Kết quả của decltype(hf) là một loại lớp mà không có constructor mặc định (nó xóa bởi =delete). Vì vậy, bạn cần truyền đối tượng bởi hàm dựng của unordered_map để cho nó xây dựng đối tượng lambda.

+1

@MM., Như sau: 'std :: unordered_map m (1, hf);'. Đối số đầu tiên là số lượng nhóm ban đầu, số thứ hai là số. Bạn không thể sử dụng brace-initialization trong trường hợp này, thật đáng buồn. – avakar

+0

Thú vị, mặc dù kinda gian lận như bạn không chỉ đi qua chức năng lambda như là một tham số mẫu. Trong thực tế, tham số mẫu có thể tránh được tất cả cùng nhau thông qua một hàm mẫu của trình trợ giúp như: 'template auto make_unordered_map (size_t bucketCount, HASHER const & hf) -> unordered_map { trả về unordered_map (bucketCount, hf); } 'như đã thấy [ở đây] (http://ideone.com/62heUn). Tuy nhiên, nó là thú vị. :) – Adrian

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