
Hi All, I have been going through the documentation of the multi_index_container in the Boot.MultiIndex library. In the example code provided I saw the use of the identity<> template. The relevant portion of the example code is reproduced here for convenience. http://www.boost.org/doc/libs/1_36_0/libs/multi_index/doc/index.html typedef multi_index_container< employee, indexed_by< // sort by employee::operator< ordered_unique<identity<employee> >, // sort by less<string> on name ordered_non_unique<member<employee,std::string,&employee::name> >
employee_set;
I am trying to understand what is the use of the identity<> template class. I also noticed the following in the documentation, "The predefined identity predicate can be used here as a key extractor; identity returns as the key the same object passed as argument." Is there any reason why the word object (instead of type) is used in that sentence? Also if the identity<> template evaluates to the type given as its argument, is there any benefit out of it? I am quite new to template meta programming and am trying to understand things. Any explanation would be very helpful. Rgds, anna -- Abusive Language on Internet http://missingrainbow.blogspot.com/2008/08/abusive-language-on-internet.html

Annamalai Gurusami <annamalai.gurusami <at> gmail.com> writes:
Hi All, http://www.boost.org/doc/libs/1_36_0/libs/multi_index/doc/index.html [...] I am trying to understand what is the use of the identity<> template class. I also noticed the following in the documentation, "The predefined identity predicate can be used here as a key extractor; identity returns as the key the same object passed as argument." Is there any reason why the word object (instead of type) is used in that sentence? Also if the identity<> template evaluates to the type given as its argument, is there any benefit out of it?
I *think* I know where your confusion stems from: identity<> is not a purely compile-time entity as some MPL constructs are, but a conventional type with real run-time functionality (I guess you are wondering why not use T directly instead of identity<T>, right?): 1. Is there any reason why the word object (instead of type) is used in that sentence? Because identity<T> operates at run time as a functor taking objects of type T: identity<std::string> i; std::string str="hello"; std::cout<<i(str)<<std::endl; // prints hello 2. Also if the identity<> template evaluates to the type given as its argument, is there any benefit out of it? identity<T> does not evaluate to T, as said before it is not a MPL metafunction but a plain functor much as, for instance, std::less<> or boost::hash<>. Clearer now? Don't hesitate to come back if doubts persist. Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

On Thu, Sep 4, 2008 at 4:51 PM, Joaquin M Lopez Munoz <joaquin@tid.es> wrote:
Because identity<T> operates at run time as a functor taking objects of type T:
identity<std::string> i; std::string str="hello"; std::cout<<i(str)<<std::endl; // prints hello
Thank you very much for the response. Now I understand that identity<> is not an MPL construct. I was reading through the identity.hpp file and I think I understand it now. It can be used to convert chained pointers and smart pointers to references. For example, int ****i; identity<int> get_ref; get_ref(i); // This will return me a reference to the integer Let me know if I got that right. But since the template arguments are type names is there any reason why we need to use identity in template arguments? For example, in the code snippet given in the documentation, (my question embedded in the code fragment below as comments), typedef multi_index_container< employee, indexed_by< ordered_unique<identity<employee> >, // Why is identity required here? // Why is ordered_unique<employee> not sufficient? ordered_non_unique<member<employee,std::string,&employee::name> >, ordered_unique<member<employee,int,&employee::ssnumber> >
employee_set;
Since the std::set doesn't require anything other than the type name of the elements it would hold, why does boost::multi_index::ordered_unique need this identity<>? What are the additional benefits of this added complexity? Rgds, anna -- Abusive Language on Internet http://missingrainbow.blogspot.com/2008/08/abusive-language-on-internet.html

Annamalai Gurusami escribió:
Thank you very much for the response. Now I understand that identity<> is not an MPL construct. I was reading through the identity.hpp file and I think I understand it now. It can be used to convert chained pointers and smart pointers to references. For example,
int ****i; identity<int> get_ref; get_ref(i); // This will return me a reference to the integer
Let me know if I got that right.
Correct. You hopefully don't need to read the code directly to learn that, as is explained at http://www.boost.org/libs/multi_index/doc/tutorial/key_extraction.html http://www.boost.org/libs/multi_index/doc/reference/key_extraction.html
But since the template arguments are type names is there any reason why we need to use identity in template arguments? For example, in the code snippet given in the documentation, (my question embedded in the code fragment below as comments),
typedef multi_index_container< employee, indexed_by< ordered_unique<identity<employee> >, // Why is identity required here? // Why is ordered_unique<employee> not sufficient? ordered_non_unique<member<employee,std::string,&employee::name> >, ordered_unique<member<employee,int,&employee::ssnumber> >
employee_set;
Since the std::set doesn't require anything other than the type name of the elements it would hold, why does boost::multi_index::ordered_unique need this identity<>? What are the additional benefits of this added complexity?
STL associative containers like std::set and std::map use the notion of a key associated to a value, although they do so in an implicit manner: set<T> --> value_type=T, key_type=T map<K,T> --> value_type=std::pair<const K,T>, key_type=K In both cases keys are extracted from value_types through a fixed process: set<T> --> key(element) = element; map<K,T> --> key(element) = element.first; // element is a std::pair So you could say that std::set and std::map implicitly use key extractors, at least in an incipient form. For instance, the key_extractor of std::set<T> is functionally equivalent to identity<T>. Boost.MultiIndex simply makes this key extractor notion explicit by having the user specify which key extractors are used for each index. Why making this explicit instead of relying on implicit key extraction mechanisms like the STL containers? The simple reason is that STL containers are singly indexed and can afford assuming a fixed key extraction process, but multi_index_containers are precisely multi-indexed, so it's almost guaranteedly the case that you'd need different keys for each index, all of them extracted from the same value_type. Hence all the key extraction framework. Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

On Fri, Sep 5, 2008 at 1:07 AM, <joaquin@tid.es> wrote:
Correct. You hopefully don't need to read the code directly to learn that, as is explained at
http://www.boost.org/libs/multi_index/doc/tutorial/key_extraction.html http://www.boost.org/libs/multi_index/doc/reference/key_extraction.html
Going through that key extraction concept helped me to understand the big picture. Thanks very much. Rgds, anna -- Abusive Language on Internet http://missingrainbow.blogspot.com/2008/08/abusive-language-on-internet.html
participants (3)
-
Annamalai Gurusami
-
Joaquin M Lopez Munoz
-
joaquin@tid.es