[bimap] How to erase a single association in a many-to-many bimap?
Hi, I have a bimap typedef bimap< multiset_of< tagged< Person*, consultant> >, multiset_of< tagged< Company*, client> >, with_info< tagged< ConsultancyContract*, contract> >
Consultancy;
initialized as follows Consultancy consultancy; Person John("John"), Jane("Jane"); Company Dell("Dell"), HP("HP"); ConsultancyContract JohnContractD(10,1); ConsultancyContract JaneContractD(20, 2); ConsultancyContract JaneContractH(30, 3); consultancy.insert(Consultancy::value_type(&Jane, &Dell, &JaneContractD)); consultancy.insert(Consultancy::value_type(&Jane, &HP, &JaneContractH)); and I want to remove only the specific association Jane<->Dell and so I'm using consultancy.erase(Consultancy::value_type(&Jane, &Dell)); but then the resulting consultancy bimap is empty, while I expect the association Jane<->HP to be there yet. If I add before erasing consultancy.insert(Consultancy::value_type(&John, &Dell, &JohnContractD)); and then consultancy.erase(Consultancy::value_type(&Jane, &Dell)); all the associations concerning Jane are removed. What I'm doing wrong? How to erase a single association? Best, Vicente
Le 15/05/12 12:09, Vicente J. Botet Escriba a écrit :
Hi,
I have a bimap
typedef bimap< multiset_of< tagged< Person*, consultant> >, multiset_of< tagged< Company*, client> >, with_info< tagged< ConsultancyContract*, contract> >
Consultancy;
initialized as follows
Consultancy consultancy; Person John("John"), Jane("Jane"); Company Dell("Dell"), HP("HP"); ConsultancyContract JohnContractD(10,1); ConsultancyContract JaneContractD(20, 2); ConsultancyContract JaneContractH(30, 3);
consultancy.insert(Consultancy::value_type(&Jane, &Dell, &JaneContractD)); consultancy.insert(Consultancy::value_type(&Jane, &HP, &JaneContractH));
and I want to remove only the specific association Jane<->Dell and so I'm using
consultancy.erase(Consultancy::value_type(&Jane, &Dell));
but then the resulting consultancy bimap is empty, while I expect the association Jane<->HP to be there yet.
If I add before erasing consultancy.insert(Consultancy::value_type(&John, &Dell, &JohnContractD));
and then consultancy.erase(Consultancy::value_type(&Jane, &Dell));
all the associations concerning Jane are removed.
What I'm doing wrong? How to erase a single association?
I have reached to get what I was locking for. I have added set_of_relation<> to the bimap definition typedef bimap< multiset_of< tagged< Person*, consultant> >, multiset_of< tagged< Company*, client> >, with_info< tagged< ConsultancyContract*, contract> > , multiset_of_relation<>
Consultancy;
Is there another way when the collection of relation is the default |left_based? |I find the default behavior a little bit surprising. Why provide a erase function requesting the value_type if only the left side is taken in account? | What is the rationale to have the default left_based? Space optimization? It works also with multiset_of_relation. I don't see a use case for this. When the user could want the same association to be several times? Could some one give me an example? Best, Vicente |
Hi Vicente,
On Tue, May 15, 2012 at 12:43 PM, Vicente J. Botet Escriba
Le 15/05/12 12:09, Vicente J. Botet Escriba a écrit :
I have a bimap
typedef bimap< multiset_of< tagged< Person*, consultant> >, multiset_of< tagged< Company*, client> >, with_info< tagged< ConsultancyContract*, contract> >
Consultancy;
initialized as follows
Consultancy consultancy; Person John("John"), Jane("Jane"); Company Dell("Dell"), HP("HP"); ConsultancyContract JohnContractD(10,1); ConsultancyContract JaneContractD(20, 2); ConsultancyContract JaneContractH(30, 3);
consultancy.insert(Consultancy::value_type(&Jane, &Dell, &JaneContractD)); consultancy.insert(Consultancy::value_type(&Jane, &HP, &JaneContractH));
and I want to remove only the specific association Jane<->Dell and so I'm using
consultancy.erase(Consultancy::value_type(&Jane, &Dell));
but then the resulting consultancy bimap is empty, while I expect the association Jane<->HP to be there yet.
I have reached to get what I was locking for.
I have added set_of_relation<> to the bimap definition
Yes, exactly this.
Is there another way when the collection of relation is the default left_based?
No, but you could write your own function to erase them.
I find the default behavior a little bit surprising. Why provide a erase function requesting the value_type if only the left side is taken in account?
I understand that is a little bit surprising, but it is exactly the same that will happen if you use and std::set<relation> with a custom Compare functor that compares left keys. In a left based set of relations, the relations are indexed by the left key and the equality is defined ignoring completely the right one.
What is the rationale to have the default left_based? Space optimization?
It is not only space optimization, but also performance. When you do not use the default, the internal Boost.MultiIndex ends up having three indexes instead of two. Maybe we should have set the default to unconstrained_set_of_relation. In that case, you will be forced to use the left or right view always. I think that we are a little bit to late in the game for that.
It works also with multiset_of_relation. I don't see a use case for this. When the user could want the same association to be several times? Could some one give me an example?
If you do not want to pay the extra cost of the third index, while being able to access the relations from above as a set of (left,right) values. So you can write code like the one you posted, where you directly use insert on the bimap instead of the views. I think the set abstraction over your data is useful. The only important thing to have in mind is that you are dealing with a set<relation> with the compare functor looking only the left key. Insertion, ordering, deletion will behave the same as in the left view. Again... using unconstrained_set_of_relation was the other option for the default, and I agree it is a very arguable choice. Best regards Matias
participants (2)
-
Matias Capeletto
-
Vicente J. Botet Escriba