2012-01-01 17 views
10

मैं निम्न कार्य करने की कोशिश कर रहा हूँ का समर्थन करने के बढ़ावा unordered_map बनाने के लिए: 'को बढ़ावा देने :: hash_value':फ्लाईवेट <string>

boost::unordered_map<boost::flyweight<std::string>, boost::flyweight<std::string> > map; 

     boost::flyweight<std::string> foo(name); 
     map[foo] = foo; 

लेकिन संकलक शिकायत: "त्रुटि C2665 17 भार के में से कोई भी कर सकता है सभी तर्क प्रकारों को परिवर्तित करें "।

लेकिन मैं निम्नलिखित समारोह को परिभाषित किया है:

std::size_t hash_value(const boost::flyweight<std::string> & b) 
{ 
    boost::hash<std::string> hasher; 
    const std::string & str = b.get(); 
    return hasher(str); 
} 
bool operator==(const boost::flyweight<std::string>& f, const boost::flyweight<std::string> & second) 
{ 
    return f.get() == second.get(); 
} 

लेकिन यह नहीं करता है संकलन।

फ्लाईवेट का समर्थन करने के लिए मुझे unordered_map को बढ़ावा देने के लिए क्या करने की आवश्यकता है?

[संपादित करें] मैं इसे निम्न कोड के साथ काम करने के लिए मिल गया:

struct flyweight_hash 
    { 
     std::size_t operator()(const boost::flyweight<std::string> &elm) const 
     { 
      boost::hash<std::string> hasher; 
      const std::string & str = elm.get(); 
      return hasher(str); 
     } 
    }; 

और नक्शे के निर्माण के लिए एक टेम्पलेट पैरामीटर के रूप में इसे पारित:

boost::unordered_map<boost::flyweight<std::string>, boost::flyweight<std::string> , flyweight_hash > map; 

इस मामले में मैं हैश_वल्यू ने काम नहीं किया है, ओवरलोडिंग तरीका समझ में नहीं आया।

उत्तर

7

boost::hash तर्क निर्भर लुकअप (एडीएल) के माध्यम से hash_value पर कॉल करता है। आप नामस्थान boost में किसी कक्षा के लिए hash_value फ़ंक्शन को परिभाषित करने का प्रयास कर रहे हैं। इसलिए आपके hash_value फ़ंक्शन को इस नामस्थान में और एडीएल के काम के लिए भी जाना होगा। दुर्भाग्यवश, एक विदेशी नामस्थान में कार्य जोड़ना बुरा है और इससे बचा जाना चाहिए। कस्टम हैशर का उपयोग करने का आपका समाधान ठीक लगता है।

एक छोटी सी उदाहरण कोड वर्णन करने के लिए:

namespace boost { 
    // somewhere in boost 
    template<typename T> 
    std::size_t hash(const T& t) { 
    // call using ADL 
    // e.g. if called with object of class type foo::bar this will 
    // pick up foo::hash_value despite the lack of namespace 
    // qualification 
    return hash_value(t); 
    } 
} 

// your hash_value (presumably in the global namespace) 
// not picked up by above call 
std::size_t hash_value(boost::flyweight<T>...); 

namespace boost { 
    // this would be picked up but is slightly evil 
    std::size_t hash_value(boost::flyweight<T>...); 
} 
+0

यह केवल खराब है क्योंकि 'boost :: unordered_map' का डिफ़ॉल्ट हैशर boost :: hash_value का उपयोग करके एडीएल को ट्रिगर नहीं करता है; वापसी हैश_वल्यू (कुंजी); '। मैं अभी यह जांच नहीं कर सकता हूं। – Xeo

+0

@Xeo डिफ़ॉल्ट हैशर 'boost :: हैश' होना चाहिए और' unordered_map' के लिए विशिष्ट नहीं होना चाहिए। कम से कम डॉक्टर ऐसा कहते हैं। – pmr

+0

निश्चित रूप से, लेकिन यह नहीं बदलेगा कि एडीएल-सक्षम कॉल का उपयोग नहीं किया जा रहा है। – Xeo

5

यह कुछ जो पहले से ही टुकड़ों में बांटा जा चुका है हैश करने के लिए एक दया है। फ्लाईवेट बराबर वस्तुओं का एक उदाहरण रखता है, इसलिए इसकी सामग्री के बजाय, इस उदाहरण के पते को हैश करना अधिक कुशल है। मैं (std में boost में नहीं, जैसा कि मैंने सी ++ 11 उपयोग कर रहा हूँ, इसलिए मैं std::hash का विस्तार कर रहा हूँ, नहीं boost::hash) के रूप में कार्य करें:

namespace std 
{ 
    template <typename T> 
    struct hash<boost::flyweight<T, boost::flyweights::no_tracking>> 
    { 
    using value_type = boost::flyweight<T, boost::flyweights::no_tracking>; 
    size_t operator()(const value_type& ss) const 
    { 
     hash<const void*> hasher; 
     return hasher(&ss.get()); 
    } 
    }; 
} 

मैं पुष्टि की गई है कि इस डिजाइन से काम करता है, दुर्घटना से नहीं: http://lists.boost.org/boost-users/2013/03/78007.php

संबंधित मुद्दे