Boost logo

Boost Users :

From: Joaquín Mª López Muñoz (joaquin_at_[hidden])
Date: 2007-04-26 06:29:48


Ovanes Markarian ha escrito:

> Hello Joaquín,
>
> now I found the failure, to the problem described in message
> http://lists.boost.org/boost-users/2007/04/27211.php with std::string as a key not being found.
> The problem in my case was that I use Xalan to parse XML and have to convert string to single byte
> characters. Since std::string has some build in caching to improve performance and I decode double
> byte string (XalanDOMString) as follows:
>
> std::string get_string(XalanDOMString const& str)
> {
> XalanDOMString::CharVectorType v;
> str.transcode(v);
>
> return std::string(v.begin(), v.end());
> }
>
> this code produces a string which still points to the double byte buffer and therefore this
> results in a different hash value for the returned string as the value would be for the
> basic_string<char> or C-String:
>
> An example:
>
> XalanDOMString str("Sint8");
> std::string char_str(get_string(str));
>
> Calling find in the multi-index results in a hash value 40.
>
> Calling find in the multi-index for
> const char* str="Sint8";
> results in a hash value 13
>
> The same result (13) can be achieved when calling on char_str.c_str(); c_str() cause the strings
> internal buffer to be rebuild.
>
> Since boost::hash is on the way to become a part of STL it should ensure to work with the
> correctly intended copy of string. What is your opinion on this issue?

OK, what's happenning is the following: boost::hash<std::string>()(str) is not equivalent
to boost<const char*>()(str.c_str()); the latter hashes the *pointer*, not the contents
pointed to. So, when you write

  your_container.find(str.c_str())

B.MI assumes that what you pass (a const char *) is equivalent hash- and equivalence-wise
to the stored keys (std::strings), which is not true (because of the hash, equivalence is
indeed interoperable as std::string provides the required overloads for operator== etc.)

Returning to your original problem, you said that this works:

  inline some_type_ptr create_type(std::string const& name)const
  {
       types_map::index<hash>::type::const_iterator i =types_.get<hash>().find(name.c_str());
       //...
  }

but this does not:

  inline some_type_ptr create_type(std::string const& name)const
  {
       types_map::index<hash>::type::const_iterator i =types_.get<hash>().find(name);
       //...
  }

This puzzles me a lot: Given that your types_map container is indexed on a std::string,
things should be the other way around: it is the "find(name)" version that should work
AFAICS. Could you please double-check?

Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net