📄 tutorial.qbk
字号:
][@../../example/tutorial_modify_and_replace.cpp Go to source code][code_tutorial_modify][endsect][section Retrieval of ranges][import ../example/tutorial_range.cpp]Standard `lower_bound` and `upper_bound` functions can be used to lookup forall the elements in a given range.Suppose we want to retrieve the elements from a `bimap<int,std::string>`where the left value is in the range `[20,50]`[code_tutorial_range_standard_way]Subtle changes to the code are required when strict inequalities are considered.To retrieve the elements greater than 20 and less than 50, the code has to be rewritten as[code_tutorial_range_standard_way_subtle_changes]To add to this complexity, the careful programmer has to take into account thatthe lower and upper bounds of the interval searched be compatible: for instance,if the lower bound is 50 and the upper bound is 20, the iterators `iter_first` and`iter_second` produced by the code above will be in reverse order, with possiblycatastrophic results if a traversal from `iter_first` to `iter_second` is tried.All these details make range searching a tedious and error prone task.The range member function, often in combination with lambda expressions,can greatly help alleviate this situation:[code_tutorial_range]`range` simply accepts predicates specifying the lower and upper bounds of the interval searched. Please consult the reference for a detailed explanation of the permissible predicates passed to range.One or both bounds can be omitted with the special unbounded marker:[code_tutorial_range_unbounded][@../../example/tutorial_range.cpp Go to source code][endsect][endsect][section Bimaps with user defined names][import ../example/user_defined_names.cpp]In the following example, the library user inserted comments to guidefuture programmers:[@../../example/user_defined_names.cpp Go to source code][code_user_defined_names_untagged_version]In Boost.Bimap there is a better way to document the code andin the meantime helping you to write more mantainable and readable code.You can tag the two collections of the bimap so they can be accessed by more descriptive names.__TAGGED__A tagged type is a type that has been labelled using a tag. A tag is anyvalid C++ type. In a bimap, the types are always tagged. If you do notspecify your own tag, the container uses `member_at::left` and`member_at::right` to tag the left and right sides respectively. In orderto specify a custom tag, the type of each side has to be tagged. Tagging a type is very simple: typedef tagged< int, a_tag > tagged_int;Now we can rewrite the example:[@../../example/user_defined_names.cpp Go to source code][code_user_defined_names_tagged_version]Here is a list of common structures in both tagged and untagged versions.Remember that when the bimap has user defined tags you can still use the untagged version structures. struct Left {}; struct Right {}; typedef bimap< multiset_of< tagged< int, Left > >, unordered_set_of< tagged< int, Right > > > bm_type; bm_type bm; //... bm_type::iterator iter = bm.begin(); bm_type::left_iterator left_iter = bm.left.begin(); bm_type::right_iterator right_iter = bm.right.begin();[table Equivalence of expresions using user defined names[[Untagged version] [Tagged version] ][[`bm.left`] [`bm.by<Left>()`] ][[`bm.right`] [`bm.by<Right>()`] ][[`bm_type::left_map`] [`bm::map_by<Left>::type`] ][[`bm_type::right_value_type`] [`bm::map_by<Right>::value_type`] ][[`bm_type::left_iterator`] [`bm::map_by<Left>::iterator`] ][[`bm_type::right_const_iterator`][`bm::map_by<Right>::const_iterator`]][[`iter->left`] [`iter->get<Left>()`] ][[`iter->right`] [`iter->get<Right>()`] ][[`left_iter->first`] [`left_iter->get<Left>()`] ][[`left_iter->second`] [`left_iter->get<Right>()`] ][[`right_iter->first`] [`right_iter->get<Right>()`] ][[`right_iter->second`] [`right_iter->get<Left>()`] ][[`bm.project_left(iter)`] [`bm.project<Left>(iter)`] ][[`bm.project_right(iter)`] [`bm.project<Right>(iter)`] ]][endsect][section Unconstrained Sets]Unconstrained sets allow the user to disable one of the views of abimap. Doing so makes the bimap operations execute faster and reducesmemory consumption. This completes the bidirectional mapping frameworkby including unidirectional mappings as a particular case.Unconstrained sets are useful for the following reasons:* A bimap type has stronger guarantees than its standard equivalent,and includes some useful functions (replace, modify) that the standarddoes not have.* You can view the mapping as a collection of relations.* Using this kind of map makes the code very extensible. If, at anymoment of the development, the need to perform searches from the rightside of the mapping arises, the only necessary change is to the `typedef`.[import ../example/unconstrained_collection.cpp]Given this bimap instance,[code_unconstrained_collection_bimap]or this standard map one[code_unconstrained_collection_map]The following code snippet is valid[code_unconstrained_collection_common]But using a bimap has some benefits[code_unconstrained_collection_only_for_bimap][@../../example/unconstrained_collection.cpp Go to source code][endsect][section Additional information][import ../example/tutorial_info_hook.cpp]Bidirectional maps may have associated information about each relation.Suppose we want to represent a books and author bidirectional map.[code_tutorial_info_hook_nothing]Suppose now that we want to store abstract of each book.We have two options:# Books name are unique identifiers, so we can create a separate`std::map< string, string >` that relates books names with abstracts.# We can use __BOOST_MULTI_INDEX__ for the new beast.Option 1 is the wrong approach, if we go this path we lost what bimap has won us. We now have to maintain the logic of two interdependent containers,there is an extra string stored for each book name, and the performance willbe worse. This is far away from being a good solution.Option 2 is correct. We start thinking books as entries in a table. So itmakes sense to start using Boost.MultiIndex. We can then add the yearof publication, the price, etc... and we can index this new items too. SoBoost.MultiIndex is a sound solution for our problem.The thing is that there are cases where we want to maintain bimapsemantics (use `at()` to find an author given a book name and the other wayaround) and add information about the relations that we are sure we will notwant to index later (like the abstracts). Option 1 is not possible, option 2neither.Boost.Bimap provides support for this kind of situations by means ofan embedded information member.You can pass an extra parameter to a bimap: `with_info< InfoType >`and an `info` member of type `InfoType` will appear in the relation and bimappairs.__RELATION_AND_PAIR_WITH_INFO__Relations and bimap pairs constructors will take an extra argument.If only two arguments are used, the information will be initialized withtheir default constructor.[code_tutorial_info_hook_first]Contrary to the two key types, the information will be mutable using iterators.[code_tutorial_info_hook_mutable]A new function is included in ['unique] map views: `info_at(key)`, that mimics thestandard `at(key)` function but returned the associated information instead ofthe data.[code_tutorial_info_hook_info_at]The info member can be tagged just as the left or the right member. The followingis a rewrite of the above example using user defined names:[code_tutorial_info_hook_tagged_info][@../../example/tutorial_info_hook.cpp Go to source code][endsect][section Complete instantiation scheme]To summarize, this is the complete instantiation scheme. typedef bimap < LeftCollectionType, RightCollectionType [ , SetTypeOfRelation ] // Default to left_based [ , with_info< Info > ] // Default to no info [ , Allocator ] // Default to std::allocator<> > bm;`{Side}CollectionType` can directly be a type. This defaults to`set_of<Type>`, or can be a `{CollectionType}_of<Type>` specification.Additionally, the type of this two parameters can be tagged to specify user defined names instead of the usual `member_at::-Side-` tags. The possibles way to use the first parameter are: bimap< Type, R >* Left type: `Type`* Left collection type: `set_of< Type >`* Left tag: `member_at::left` bimap< {CollectionType}_of< Type >, R >* Left type: `Type`* Left collection type: `{CollectionType}_of< LeftType >`* Left tag: `member_at::left` bimap< tagged< Type, Tag >, R >* Left type: `Type`* Left collection type: `set_of< LeftType >`* Left tag: `Tag` bimap< {CollectionType}_of< tagged< Type, Tag > >, R >* Left type: `Type`* Left collection type: `{CollectionType}_of< LeftType >`* Left tag: `Tag`The same options are available for the second parameter.The last three parameters are used to specify the collection type of the relation,the information member and the allocator type.If you want to specify a custom allocator type while relying on the defaultvalue of CollectionTypeOfRelation, you can do so by simply writing`bimap<LeftKeyType, RightKeyType, Allocator>`. Boost.Bimap's internalmachinery detects that the third parameter in this case does not referto the relation type but rather to an allocator.The following are the possible ways of instantiating the last three parametersof a bimap. You can ignore some of the parameter but the order must be respected. bimap< L, R >* set_of_relation_type: based on the left key type* info: no info* allocator: std::allocator bimap< L, R ,SetOfRelationType>* set_of_relation_type: SetOfRelationType* info: no info* allocator: std::allocator bimap< L, R , SetOfRelationType, with_info<Info> >* set_of_relation_type: SetOfRelationType* info: Info* allocator: std::allocator bimap< L, R , SetOfRelationType, with_info<Info>, Allocator>* set_of_relation_type: SetOfRelationType* info: Info* allocator: Allocator bimap< L, R , SetOfRelationType, Allocator>* set_of_relation_type: SetOfRelationType* info: no info* allocator: Allocator bimap< L, R , with_info<Info> >* set_of_relation_type: based on the left key type* info: Info* allocator: std::allocator bimap< L, R , with_info<Info>, Allocator>* set_of_relation_type: based on the left key type* allocator: Allocator bimap< L, R , Allocator>* set_of_relation_type: based on the left key type* info: no info* allocator: Allocator[endsect][endsect]
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -