2013-07-26 8 views
9

मैं क्रॉस-प्लेटफ़ॉर्म सी ++ एप्लिकेशन में std :: unordered_set का उपयोग करने का प्रयास कर रहा हूं। यह विंडोज के तहत विजुअल सी ++ में एक आकर्षण की तरह संकलित करता है और काम करता है, लेकिन मैक ओएस एक्स के तहत क्लैंग पर घातक संकलन त्रुटि उत्पन्न करता है।विज़ुअल सी ++ में सी ++ 11 अनॉर्डर्ड_सेट का उपयोग करना और

मैं जानना चाहता हूं कि ऐसा क्यों होता है और यह काम करने का सही तरीका क्या है।

उदाहरण कोड:

// 
// 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; 
    } 
} 

बजना उत्पादन:

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.  

युपीडी कार्य कार्यान्वयन @ mfontanini के सुझाव का उपयोग कर: https://gist.github.com/vbo/6090142

+0

आपको हैश फ़ंक्शन/फ़ैक्टर प्रदान करने की आवश्यकता है। – juanchopanza

उत्तर

17

के लिए अपने Point वर्ग के साथ std::unordered_set काम करने के लिए है, तो आप इसके लिए एक std::hash विशेषज्ञता प्रदान कर सकते हैं:

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

तुम भी std::unordered_set के दूसरे टेम्पलेट पैरामीटर (यह चूक std::hash<Point> करने के लिए) को बदल सकता है, जो इंगित करता एक मज़ेदार प्रकार जो आवश्यक हैश देता है।

ऐसा लगता है कि आपने size_t पर उपयोगकर्ता परिभाषित रूपांतरण के माध्यम से इस हैश कार्यान्वयन को प्रदान करने का प्रयास किया है, लेकिन यह काम नहीं करेगा। तथ्य यह है कि यह वीसी में काम करता है उनके कार्यान्वयन में कुछ बग के कारण होता है।

+0

@juanchopanza दाएं, उसको याद किया। धन्यवाद। – mfontanini

+0

ठीक है, अच्छा लगता है। लेकिन यह विजुअल स्टूडियो में क्यों काम करता है? – vbo

+0

@ vbo जाहिर है, वीसी के कार्यान्वयन को गड़बड़ कर दिया गया है, जिससे आपके उपयोगकर्ता ने रूपांतरण कार्य को परिभाषित किया है। – mfontanini