$include_dir="/home/hyper-archives/boost-users/include"; include("$include_dir/msg-header.inc") ?>
Subject: Re: [Boost-users] boost::multi_index
From: Priyank Patel (ppatel_at_[hidden])
Date: 2011-04-08 12:34:45
Thanks a lot for replies.
On 04/08/2011 01:26 AM, joaquin_at_[hidden] wrote:
> El 07/04/2011 16:20, Dominique Devienne escribió:
>    
>> On Wed, Apr 6, 2011 at 1:54 PM,<ppatel_at_[hidden]>   wrote:
>>      
>>> I have a question regarding creating composite key/specifying length for
>>> arrays while using multi_index container based on following structure.
>>>
>>> struct TestStruct {
>>>                   char firstKey[50];
>>>                   char secondKeyPart[3];
>>>                   uint32_t thirdKeyPart;
>>>                   
Some other information
.
>>> };
>>>        
>> Using a composite key and associated hasher/equalTo types yields some
>> pretty long (and ugly?) types for the multi-index
>> container/extractor/hasher/equaler. If "
Some other information
." is
>> not too large such that TestStruct is not too expensive to construct,
>> you're often better of using the identity key extractor, and implement
>> the hasher and op== in terms of TestStruct itself. The only downside I
>> see is that you must constructs a whole new TestStruct when you want
>> to look one up instead of doing a make_tuple(part1, part2, part3),
>> which is why I mentioned above "if TestStruct is not too expensive to
>> construct". This is the route we followed, away from composite keys
>> and into custom hasher/equaler of our own structs. Not sure if Joaquin
>> also recommend that route, but it worked fine for us and makes things
>> simpler IMHO. --DD
>>      
> I leans towards the composite_key solution, as it more clearly expresses the intention
> than the equivalent, hand-coded solution, but this is after all a matter of personal
> taste.
>
> As for the downside you refer to, having to create a potentially expensive TestStruct,
> Boost.MultiIndex features so-called compatible keys, which can come to the rescue here:
>
> http://www.boost.org/libs/multi_index/doc/tutorial/basics.html#special_lookup
>
> The idea is that you can simply use some structure that contains the key info without
> the overload and make this interoperable with TestStruct with respect to hashing and
> equality comparison:
>
>     struct TestStructKeyInfo
>     {
>       TestStructKeyInfo(const char* f,const char* s,uint32_t t)
>       {
>         std::strcpy(firstKeyPart,f);
>         std::strcpy(secondKeyPart,s);
>         thirdKeyPart=t;
>       }
>
>       char firstKeyPart[50];
>       char secondKeyPart[3];
>       uint32_t thirdKeyPart;
>     };
>
>     std::size_t hash_value(const TestStruct&  t)
>     {
>       std::size_t seed=0;
>       for(const char* str=t.firstKeyPart;*str;++str)
>         boost::hash_combine(seed,*str);
>       for(const char* str=t.secondKeyPart;*str;++str)
>         boost::hash_combine(seed,*str);
>       boost::hash_combine(seed,t.thirdKeyPart);
>       return seed;
>     }
>
>     std::size_t hash_value(const TestStructKeyInfo&  t)
>     {
>       std::size_t seed=0;
>       for(const char* str=t.firstKeyPart;*str;++str)
>         boost::hash_combine(seed,*str);
>       for(const char* str=t.secondKeyPart;*str;++str)
>         boost::hash_combine(seed,*str);
>       boost::hash_combine(seed,t.thirdKeyPart);
>       return seed;
>     }
>
>     bool operator==(const TestStruct&  t1,const TestStruct&  t2)
>     {
>       return
>         std::strcmp(t1.firstKeyPart,t2.firstKeyPart)==0&&
>         std::strcmp(t1.secondKeyPart,t2.secondKeyPart)==0&&
>         t1.thirdKeyPart==t2.thirdKeyPart;
>     }
>
>     bool operator==(const TestStruct&  t1,const TestStructKeyInfo&  t2)
>     {
>       return
>         std::strcmp(t1.firstKeyPart,t2.firstKeyPart)==0&&
>         std::strcmp(t1.secondKeyPart,t2.secondKeyPart)==0&&
>         t1.thirdKeyPart==t2.thirdKeyPart;
>     }
>
>     bool operator==(const TestStructKeyInfo&  t1,const TestStruct&  t2)
>     {
>       return
>         std::strcmp(t1.firstKeyPart,t2.firstKeyPart)==0&&
>         std::strcmp(t1.secondKeyPart,t2.secondKeyPart)==0&&
>         t1.thirdKeyPart==t2.thirdKeyPart;
>     }
>
> so that you can define the container like this:
>
>     struct TestStructHash:
>       boost::hash<TestStruct>,
>       boost::hash<TestStructKeyInfo>
>     {
>       using boost::hash<TestStruct>::operator();
>       using boost::hash<TestStructKeyInfo>::operator();
>     };
>
>     struct TestStructEqualTo:std::equal_to<TestStruct>
>     {
>       using std::equal_to<TestStruct>::operator();
>       bool operator()(const TestStruct&  t1,const TestStructKeyInfo&  t2)const
>       {
>         return t1==t2;
>       }
>       bool operator()(const TestStructKeyInfo&  t1,const TestStruct&  t2)const
>       {
>         return t1==t2;
>       }
>     };
>
>     typedef multi_index_container<
>       TestStruct,
>       indexed_by<
>         hashed_unique<
>           identity<TestStruct>,
>           TestStructHash,
>           TestStructEqualTo
>   >
>   >
>   >  TS;
>
> and use TestStructKeyInfo for lookup operations:
>
>     TS::iterator it=ts.find(TestStructKeyInfo("hello","ab",2));
>
> This is, after all, not much different from passing tuples around when using
> composite keys.
>
> Joaquín M López Muñoz
> Telefónica, Investigación y Desarrollo
>
>
> Este mensaje se dirige exclusivamente a su destinatario. Puede consultar nuestra política de envío y recepción de correo electrónico en el enlace situado más abajo.
> This message is intended exclusively for its addressee. We only send and receive email on the basis of the terms set out at.
> http://www.tid.es/ES/PAGINAS/disclaimer.aspx
> _______________________________________________
> Boost-users mailing list
> Boost-users_at_[hidden]
> http://listarchives.boost.org/mailman/listinfo.cgi/boost-users
>