
Hello,
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....
};
Do I really read to specify this lengths for character arrays? If yes, how do I do that while specifying key parts as below?
typedef multi_index_container <
TestStruct,
indexed_by<
//non-unique as some subscribers might have more than one number
hashed_unique<
composite_key<
TestStruct,
member
TS;
Thanks

2011/4/6
Hello,
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….
};
Do I really read to specify this lengths for character arrays? If yes, how do I do that while specifying key parts as below?
typedef multi_index_container <
TestStruct,
indexed_by<
//non-unique as some subscribers might have more than one number
hashed_unique<
composite_key<
TestStruct,
member
, member
, member
, >
>
>
TS;
The above keys will hash the pointer values, which is probably not what you want. If you change plain C arrays to std::string, it will work as you expect.

Thanks for your answer Igor. Unfortunately that is out of my control.
This is the type of structure we used across multiple applications. I
was checking key extractors and I think that might work but haven't
tried out yet.
Thanks
Priyank
On Apr 6, 2011, at 3:32 PM, "Igor R"
2011/4/6
: Hello,
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….
};
Do I really read to specify this lengths for character arrays? If yes, how do I do that while specifying key parts as below?
typedef multi_index_container <
TestStruct,
indexed_by<
//non-unique as some subscribers might have more than one number
hashed_unique<
composite_key<
TestStruct,
member
, member
, member
, >
>
TS;
The above keys will hash the pointer values, which is probably not what you want. If you change plain C arrays to std::string, it will work as you expect. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

ppatel@archelongroup.com escribió:
Thanks for your answer Igor. Unfortunately that is out of my control. This is the type of structure we used across multiple applications. I was checking key extractors and I think that might work but haven't tried out yet.
Hello Priyank, Please don't top-post: http://www.boost.org/community/policy.html#quoting The rest of my answer below.
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….
};
Do I really read to specify this lengths for character arrays? If yes, how do I do that while specifying key parts as below?
typedef multi_index_container <
TestStruct,
indexed_by<
//non-unique as some subscribers might have more than one number
hashed_unique<
composite_key<
TestStruct,
member
, member
, member
, >
>
TS;
The above keys will hash the pointer values, which is probably not what you want. If you change plain C arrays to std::string, it will work as you expect.
Leaving aside the fact that the syntax for member that you've used us
incorrect (see the
following example for the proper usage), Igor correctly points out that
you'd be hashing
pointers rather than the strings these arrays contain. The way to do
this is by providing
user-defined hashers and equality comparers as explained in
http://www.boost.org/libs/multi_index/doc/tutorial/key_extraction.html#compo...
So, in your particular example we can have something like this:
struct CStrHasher // (C) Ion Gaztañaga
{
std::size_t operator()(const char *str)const
{
std::size_t seed = 0;
for(;*str;++str)boost::hash_combine(seed,*str);
return seed;
}
};
struct CStrEqualTo
{
bool operator()(const char *str1,const char *str2)const
{
return std::strcmp(str1,str2)==0;
}
};
typedef multi_index_container<
TestStruct,
indexed_by<
hashed_unique<
composite_key<
TestStruct,
member
TS;
Hope this helps, 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

On 04/07/2011 01:22 AM, joaquin@tid.es wrote:
ppatel@archelongroup.com escribió:
Thanks for your answer Igor. Unfortunately that is out of my control. This is the type of structure we used across multiple applications. I was checking key extractors and I think that might work but haven't tried out yet.
Hello Priyank,
Please don't top-post: http://www.boost.org/community/policy.html#quoting
The rest of my answer below.
I will keep that in mind from this email and onwards.
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….
};
Do I really read to specify this lengths for character arrays? If yes, how do I do that while specifying key parts as below?
typedef multi_index_container<
TestStruct,
indexed_by<
//non-unique as some subscribers might have more than one number
hashed_unique<
composite_key<
TestStruct,
member
, member
, member
, >
>
TS;
The above keys will hash the pointer values, which is probably not what you want. If you change plain C arrays to std::string, it will work as you expect.
Leaving aside the fact that the syntax for member that you've used us incorrect (see the following example for the proper usage), Igor correctly points out that you'd be hashing pointers rather than the strings these arrays contain. The way to do this is by providing user-defined hashers and equality comparers as explained in http://www.boost.org/libs/multi_index/doc/tutorial/key_extraction.html#compo...
So, in your particular example we can have something like this:
struct CStrHasher // (C) Ion Gaztañaga { std::size_t operator()(const char *str)const { std::size_t seed = 0; for(;*str;++str)boost::hash_combine(seed,*str); return seed; } };
struct CStrEqualTo { bool operator()(const char *str1,const char *str2)const { return std::strcmp(str1,str2)==0; } };
typedef multi_index_container< TestStruct, indexed_by< hashed_unique< composite_key< TestStruct, member
, member , member >, composite_key_hash< CStrHasher, CStrHasher, boost::hash >, composite_key_equal_to< CStrEqualTo, CStrEqualTo, std::equal_to > > > TS;
Hope this helps,
Yes. For sure. I will try this out and get back to you in case of any questions. Thanks a lot for quick reply.
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@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

On Wed, Apr 6, 2011 at 1:54 PM,
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 PS: Note that the custom hash/equal functors end up being equivalent hand-written versions of the template-based composite_key_* types would have been, but then it's simple straight forward code which is easier to understand when you debug too.

El 07/04/2011 16:20, Dominique Devienne escribió:
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
On Wed, Apr 6, 2011 at 1:54 PM,
wrote: 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_looku... 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

Thanks a lot for replies. On 04/08/2011 01:26 AM, joaquin@tid.es wrote:
El 07/04/2011 16:20, Dominique Devienne escribió:
On Wed, Apr 6, 2011 at 1:54 PM,
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_looku...
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@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (5)
-
Dominique Devienne
-
Igor R
-
joaquin@tid.es
-
ppatel@archelongroup.com
-
Priyank Patel