2012-01-08 35 views
5

Tôi đang viết một lớp có unordered_set thuộc loại riêng của nó làm thành viên. Vì vậy, tôi cần viết chuyên môn cho hash<Foo>. Chuyên môn này cần phải được xác định sau khi Foo được khai báo. Nhưng có vẻ như tôi đã cần chuyên môn hóa cho hash<Foo> trước khi xác định thành viên unordered_set<Foo>. Ít nhất nó không biên dịch và thất bại ở đó. Tôi đã thử một tuyên bố về phía trước của mẫu băm nhưng không thể làm cho nó làm việc do đó hoặc.std :: unordered_set <Foo> là thành viên của lớp Foo

Đoạn mã có liên quan là:

class Foo { 
public: 
    int i; 
    std::unordered_set<Foo> dummy; 
    Peer(std::unordered_set<Foo>); 
}; 

namespace std { 
    template<> struct hash<Foo> 
    { 
     size_t operator()(const Foo& f) const 
     { 
      return hash<int>()(f.i); 
     } 
    }; 
} 

Cảm ơn trước

Trả lời

8

Foo không thể có một biến thành viên kiểu std::unordered_set<Foo>.

Bạn không thể khởi tạo vùng chứa Thư viện chuẩn với loại không đầy đủ. Về cơ bản, với một số ngoại lệ không có liên quan ở đây, một loại lớp không hoàn thành cho đến khi } kết thúc định nghĩa của nó.

Bạn cần phải lưu trữ một số loại khác trong vùng chứa (có thể là std::unique_ptr<Foo>) hoặc sử dụng thư viện vùng chứa cung cấp thùng chứa với loại không hoàn chỉnh (ví dụ: Boost có thư viện vùng chứa).

+0

Cảm ơn câu trả lời nhanh, sau đó tôi sẽ thử nó một cách khác nhau – devmapal

+0

Vì một số lý do, Clang sẽ cho phép hành vi này. GCC xác định chính xác một vấn đề. – vmrob

1

Bạn có thể di chuyển tờ khai xung quanh một chút để làm cho nó biên dịch:

class Foo; 

namespace std { 
    template<> struct hash<Foo> { 
    size_t operator()(const Foo& f) const; 
    }; 
} 

class Foo { 
public: 
    int i; 
    std::unordered_set<Foo> dummy; 
    Foo(std::unordered_set<Foo>); 
}; 

namespace std { 
    size_t hash<Foo>::operator()(const Foo& f) const { 
    return hash<int>()(f.i); 
    } 
} 

Như James nói, tuy nhiên, việc kê khai của dummy là là hành vi không xác định.

Bạn cũng sẽ cần so sánh bình đẳng; dễ nhất để thêm operator== vào Foo.

Tôi cũng khuyên bạn nên tạo hàm tạo của Foo lấy đối số bằng tham chiếu const.

+0

Có, nó biên dịch. Nhưng vì nó thực sự không nên biên dịch bởi vì nó không phải compartant standart tôi không nên sử dụng nó như thế này, phải không? – devmapal

+0

@devmapal: Tuyệt đối đúng, không sử dụng điều này. Tôi vừa đăng trong trường hợp bạn có các kịch bản mẫu khác trong tương lai, điều này có thể áp dụng. Lưu ý rằng vấn đề chỉ là tiêu chuẩn nói rằng bạn không được để điều này * với các mẫu thư viện chuẩn *. Bạn được tự do làm điều này với các mẫu của riêng bạn nếu bạn có thể chứng minh rằng nó làm điều đúng. –

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