[multi-index] how to use in herit member as index

//boost #include <boost/multi_index_container.hpp> #include <boost/multi_index/hashed_index.hpp> #include <boost/multi_index/member.hpp> using namespace ::boost; using namespace ::boost::multi_index; #include <string> struct Peer { std::string userid; }; struct CPeer:public Peer { int index; }; struct userid{}; typedef multi_index_container< CPeer, indexed_by< hashed_unique<tag<userid>,member<CPeer,std::string,&CPeer::userid> >
CPeersType;
//how could i use userid as an index in CPeer ,not in Peer, 一 起 来,150 万 人 同 时 在 玩 的 梦 幻 西 游

----- Mensaje original ----- De: hongleij@126.com Fecha: Miércoles, Junio 27, 2007 10:16 am Asunto: [Boost-users] [multi-index] how to use in herit member as index Para: boost-users@lists.boost.org
//boost #include <boost/multi_index_container.hpp> #include <boost/multi_index/hashed_index.hpp> #include <boost/multi_index/member.hpp> using namespace ::boost; using namespace ::boost::multi_index;
#include <string>
struct Peer { std::string userid; }; struct CPeer:public Peer { int index; }; struct userid{};
typedef multi_index_container< CPeer, indexed_by<
hashed_unique<tag<userid>,member<CPeer,std::string,&CPeer::userid> >
CPeersType;
//how could i use userid as an index in CPeer ,not in Peer,
Hello, If you're using Boost 1.34, then you can simply use hashed_unique< tag<userid>, member<Peer,std::string,&Peer::userid> > (note we're writing Peer here rather than CPeer.) If you can't afford upgrading to Boost 1.34, you must use a custom key extractor: struct UseridExtractor { typedef std::string result_type; const std::string& operator()(const CPeer& cp)const { return cp.userid; } }; typedef multi_index_container< CPeer, indexed_by< hashed_unique<tag<userid>,UseridExtractor> >
CPeersType;
(more on custom key extractors at http://tinyurl.com/39shzv ). Thank you for using Boost.MultiIndex, Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

If you're using Boost 1.34, then you can simply use
hashed_unique< tag<userid>, member<Peer,std::string,&Peer::userid> >
Hi, I'm just curious - is there a reason why "member" takes 3 template parameters, and not just one, like in member<&Peer::userid> ? The first two types can be extracted from the member pointer, so I find this a bit redundant... Thanks, Filip

Filip Konvi?ka ha escrito:
If you're using Boost 1.34, then you can simply use
hashed_unique< tag<userid>, member<Peer,std::string,&Peer::userid> >
Hi,
I'm just curious - is there a reason why "member" takes 3 template parameters, and not just one, like in
member<&Peer::userid>
? The first two types can be extracted from the member pointer, so I find this a bit redundant...
It certainly looks redundant, but it turns out you really cannot do what you propose: template<...> struct member; What should "..." look like? It's not a type parameter, but it cannot be made a non-type parameter either since we don't know the type of the pointer-to-member being passed... In decltype- (or typeof-) enabled compilers a terser syntax could be achieved by using some macro hackery: template<typename PtrToMemberType,PtrToMemberType PtrToMember> struct member; #define MEMBER(PtrToMember) \ member<decltype(PtrToMember),PtrToMember> So maybe when C++0x arrives we can take advantage of this. Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

I'm just curious - is there a reason why "member" takes 3 template parameters, and not just one, like in
member<&Peer::userid>
? The first two types can be extracted from the member pointer, so I find this a bit redundant...
It certainly looks redundant, but it turns out you really cannot do what you propose:
template<...> struct member;
What should "..." look like? It's not a type parameter, but it cannot be made a non-type parameter either since we don't know the type of the pointer-to-member being passed...
In decltype- (or typeof-) enabled compilers a terser syntax could be achieved by using some macro hackery:
template<typename PtrToMemberType,PtrToMemberType PtrToMember> struct member;
#define MEMBER(PtrToMember) \ member<decltype(PtrToMember),PtrToMember>
So maybe when C++0x arrives we can take advantage of this.
I use this template in my code: template<typename T> struct get_pointer_to_member_details; template<typename Class, typename Member> struct get_pointer_to_member_details<Member Class::*> { typedef Class class_type; typedef Member member_type; }; Using this, you can write (and I do) something like template<typename MemberPointerType> struct member { MemberPointerType pMember; typedef typename get_pointer_to_member_details<MemberPointerType>::class_type class_type; typedef typename get_pointer_to_member_details<MemberPointerType>::member_type result_type; member(MemberPointerType pMember) : pMember(pMember) {} // ... } I wonder then, is it MSVC 8 that allows something non-standard, or is it OK? I think I tried with recent gcc as well and it worked... Cheers, Filip

Filip Konvi?ka ha escrito: [...]
I use this template in my code:
template<typename T> struct get_pointer_to_member_details;
template<typename Class, typename Member> struct get_pointer_to_member_details<Member Class::*> { typedef Class class_type; typedef Member member_type; };
Using this, you can write (and I do) something like
template<typename MemberPointerType> struct member { MemberPointerType pMember; typedef typename get_pointer_to_member_details<MemberPointerType>::class_type class_type; typedef typename get_pointer_to_member_details<MemberPointerType>::member_type result_type;
member(MemberPointerType pMember) : pMember(pMember) {} // ... }
I wonder then, is it MSVC 8 that allows something non-standard, or is it OK? I think I tried with recent gcc as well and it worked...
Your code is fine, but it does not do what boost::multi_index::member is meant to do, namely accepting the pointer-to-member as a template parameter --rather, you're taking it as a runtime variable in construction time. Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

Joaquín Mª López Muñoz (28.6.2007 9:49):
Filip Konvi?ka ha escrito: [...]
I use this template in my code:
template<typename T> struct get_pointer_to_member_details;
template<typename Class, typename Member> struct get_pointer_to_member_details<Member Class::*> { typedef Class class_type; typedef Member member_type; };
Using this, you can write (and I do) something like
template<typename MemberPointerType> struct member { MemberPointerType pMember; typedef typename get_pointer_to_member_details<MemberPointerType>::class_type class_type; typedef typename get_pointer_to_member_details<MemberPointerType>::member_type result_type;
member(MemberPointerType pMember) : pMember(pMember) {} // ... }
I wonder then, is it MSVC 8 that allows something non-standard, or is it OK? I think I tried with recent gcc as well and it worked...
Your code is fine, but it does not do what boost::multi_index::member is meant to do, namely accepting the pointer-to-member as a template parameter --rather, you're taking it as a runtime variable in construction time. Ah, I see...but duplicating the argument using a macro might work, like this:
#define MEMBER(MemPtr) member<get_details<MemPtr>::class_type, get_details<MemPtr>::member_type, MemPtr> The reason why I think this is better is that when you change the member type in class declaration, you have to go through all member<> usages and change the type there too. So I guess I can define this macro if I want to use it :-) Cheers, Filip

Filip Konvi?ka ha escrito:
JoaquÃn Mª López Muñoz (28.6.2007 9:49):
Filip Konvi?ka ha escrito: [...]
I use this template in my code:
template<typename T> struct get_pointer_to_member_details;
template<typename Class, typename Member> struct get_pointer_to_member_details<Member Class::*> { typedef Class class_type; typedef Member member_type; };
Using this, you can write (and I do) something like
template<typename MemberPointerType> struct member { MemberPointerType pMember; typedef typename get_pointer_to_member_details<MemberPointerType>::class_type class_type; typedef typename get_pointer_to_member_details<MemberPointerType>::member_type result_type;
member(MemberPointerType pMember) : pMember(pMember) {} // ... }
I wonder then, is it MSVC 8 that allows something non-standard, or is it OK? I think I tried with recent gcc as well and it worked...
Your code is fine, but it does not do what boost::multi_index::member is meant to do, namely accepting the pointer-to-member as a template parameter --rather, you're taking it as a runtime variable in construction time. Ah, I see...but duplicating the argument using a macro might work, like this:
#define MEMBER(MemPtr) member<get_details<MemPtr>::class_type, get_details<MemPtr>::member_type, MemPtr>
Umm... no, not quite so. MemPtr is a non-type parameter, so you'd have to write: #define MEMBER(MemPtr) \ member< \ get_details<decltype(MemPtr)>::class_type, \ get_details<decltype(MemPtr)>::member_type, \ MemPtr> So we have the need for a typeof-like facility agian :(
The reason why I think this is better is that when you change the member type in class declaration, you have to go through all member<> usages and change the type there too.
I agree with you having a macro like this makes usage simpler --but I haven't provided the macro because typeof or decltype is not standard and/or widely supported, and I don't know how to implement the macro without some of those. If you use GCC, which provides typeof(), then indeed you can write your private MEMBER utility in the manner described. Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

Ah, I see...but duplicating the argument using a macro might work, like this:
#define MEMBER(MemPtr) member<get_details<MemPtr>::class_type, get_details<MemPtr>::member_type, MemPtr>
Umm... no, not quite so. MemPtr is a non-type parameter, so you'd have to write:
Of course...I was probably too tired yesterday :-) Thanks for explaining. Cheers, Filip
participants (4)
-
"JOAQUIN LOPEZ MU?Z"
-
Filip Konvička
-
hongleij@126.com
-
Joaquín Mª López Muñoz