
Daniel James escribió:
2009/9/2 <joaquin@tid.es>:
You don't need SFINAE in order to implement compatible keys, it's much simpler than that, let me sketch how it goes. Say for instance we want to extend your find member function to support compatible keys. Currently this member function looks like:
const_iterator find(const key_type& k) const { // uses hash_function()(k), key_eq()(k,x), key_eq()(x,k) }
Now you only have to templatize find (and the internal member functions this relies on) on the key type, while leaving the code itself untouched:
template<typename CompatibleKey> const_iterator find(const CompatibleKey& k) const { // uses hash_function()(k), key_eq()(k,x), key_eq()(x,k) }
When the user calls find with a regular key_type value, everything works as it used to. When the value passed is of some other type, the code will automatically use the correct overloads of hash_function and key_eq, provided
But those overloads don't always exist. A simple example is:
struct hash { std::size_t operator()(std::string const&) const; };
struct equals { bool operator()(std::string const&, std::string const&) const; };
boost::unordered_map<std::string, int, hash, equals> map; // .... map.find("char array");
A single string object should be created in this case.
Correct, but it's the user's responsibility, not yours, to make sure the hash and equality functors used have the appropriate overloads. It's the user whose violating the member function usage interface --strictly speaking she is not violating it, as hash accepts a const char* through the construction of a temporary string, and similarly for equals, but of course this is not the intended behavior. Joaquín M López Muñoz Telefónica, Investigación y Desarrollo