2013-07-26 150 views
9

Tôi đang cố gắng sử dụng lệnh std :: unordered_set trong ứng dụng C++ đa nền tảng. Nó biên dịch và hoạt động như một nét duyên dáng trong Visual C++ trong Windows, nhưng tạo ra một lỗi biên dịch chết người trên clang dưới Mac OS X.Sử dụng C++ 11 unordered_set trong Visual C++ và clang

Tôi muốn biết tại sao nó xảy ra và cách nào là đúng để làm việc này.

Ví dụ mã:

// 
// Clang build cmdline: 
// $ clang++ ./set.cpp -Wall -Werror -Wfatal-errors -std=c++11 -stdlib=libc++ -o set.out 
// 

#include <iostream> 
#include <unordered_set> 

struct Point { 
    int x, y; 
    Point(int x = 0, int y = 0) { 
     this->x = x; 
     this->y = y; 
    } 
    bool operator==(Point const& p) const { 
     return this->x == p.x && this->y == p.y; 
    } 
    operator std::size_t() const { 
     return std::hash<int>()(x)^std::hash<int>()(y); 
    } 
}; 

typedef std::unordered_set<Point> points_set_t; 

int main() { 
    Point point1(1, 5); 
    Point point2(1, 1); 
    Point point3(1, 5); 
    points_set_t points; 
    points.insert(point1); 
    points.insert(point2); 
    points.insert(point3); 
    for (points_set_t::const_iterator it = points.begin(); it != points.end(); it++) { 
     std::cout << it->x << ":" << it->y << std::endl; 
    } 
} 

Clang đầu ra:

In file included from ./set.cpp:6: 
In file included from /usr/bin/../lib/c++/v1/iostream:38: 
In file included from /usr/bin/../lib/c++/v1/ios:216: 
In file included from /usr/bin/../lib/c++/v1/__locale:15: 
In file included from /usr/bin/../lib/c++/v1/string:434: 
In file included from /usr/bin/../lib/c++/v1/algorithm:591: 
/usr/bin/../lib/c++/v1/type_traits:748:38: fatal error: implicit instantiation of undefined template 'std::__1::hash<Point>' 
    : public integral_constant<bool, __is_empty(_Tp)> {}; 
            ^
/usr/bin/../lib/c++/v1/memory:1948:40: note: in instantiation of template class 'std::__1::is_empty<std::__1::hash<Point> >' 
     requested here 
           bool = is_empty<_T2>::value 
            ^
/usr/bin/../lib/c++/v1/memory:1970:44: note: in instantiation of default argument for '__libcpp_compressed_pair_switch<unsigned 
     long, std::__1::hash<Point>, false, false>' required here 
template <class _T1, class _T2, unsigned = __libcpp_compressed_pair_switch<_T1, _T2>::value> 
              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
/usr/bin/../lib/c++/v1/memory:2354:15: note: in instantiation of default argument for '__libcpp_compressed_pair_imp<unsigned long, 

     std::__1::hash<Point> >' required here 
    : private __libcpp_compressed_pair_imp<_T1, _T2> 
       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
/usr/bin/../lib/c++/v1/__hash_table:527:55: note: in instantiation of template class 'std::__1::__compressed_pair<unsigned long, 
     std::__1::hash<Point> >' requested here 
    __compressed_pair<size_type, hasher>    __p2_; 
                ^
/usr/bin/../lib/c++/v1/unordered_set:330:13: note: in instantiation of template class 'std::__1::__hash_table<Point, 
     std::__1::hash<Point>, std::__1::equal_to<Point>, std::__1::allocator<Point> >' requested here 
    __table __table_; 
      ^
./set.cpp:28:18: note: in instantiation of template class 'std::__1::unordered_set<Point, std::__1::hash<Point>, 
     std::__1::equal_to<Point>, std::__1::allocator<Point> >' requested here 
    points_set_t points; 
       ^
/usr/bin/../lib/c++/v1/memory:3076:29: note: template is declared here 
template <class _Tp> struct hash; 
          ^
1 error generated.  

UPD thi Làm việc sử dụng gợi ý @ mfontanini của: https://gist.github.com/vbo/6090142.

+0

Bạn cần cung cấp hàm băm/hàm functor. – juanchopanza

Trả lời

17

Để thực hiện std::unordered_set làm việc với lớp Point của bạn, bạn có thể cung cấp một chuyên môn hóa std::hash cho nó:

namespace std 
{ 
template<> 
struct hash<Point> { 
    size_t operator()(const Point &pt) const { 
     return std::hash<int>()(pt.x)^std::hash<int>()(pt.y); 
    } 
}; 
} 

Bạn cũng có thể thay đổi std::unordered_set 's tham số mẫu thứ hai (nó mặc định là std::hash<Point>), mà chỉ ra một loại functor trả về băm yêu cầu.

Dường như bạn đã thử cung cấp triển khai băm này thông qua chuyển đổi do người dùng xác định thành size_t, nhưng điều đó sẽ không hoạt động. Thực tế là nó hoạt động trong VC được gây ra bởi một số lỗi trong việc thực hiện của họ.

+0

@juanchopanza đúng, bỏ lỡ điều đó. Cảm ơn. – mfontanini

+0

Ok, âm thanh tốt. Nhưng tại sao nó hoạt động trong Visual Studio? – vbo

+0

@vbo rõ ràng, việc triển khai của VC bị lỗi, làm cho công việc chuyển đổi do người dùng xác định của bạn. – mfontanini

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