From 54a5f8f55f566f8cbdbe4f745227cef1267bab1e Mon Sep 17 00:00:00 2001 From: Aleksey Gurtovoy Date: Mon, 15 Nov 2004 12:24:13 +0000 Subject: [PATCH] new MPL docs [SVN r26212] --- doc/article.css | 67 - doc/index.html | 92 +- doc/msxsl_build.bat | 15 - doc/paper/article.css | 87 - doc/paper/html/acknowl.html | 59 - doc/paper/html/article.css | 82 - doc/paper/html/codegeneration.html | 124 -- doc/paper/html/example.html | 325 --- doc/paper/html/index.html | 181 -- doc/paper/html/intro.html | 359 ---- doc/paper/html/lambda.html | 165 -- doc/paper/html/refs.html | 152 -- doc/paper/html/usage.html | 920 -------- doc/paper/html/xsltproc_build.bat | 11 - doc/paper/mpl_paper.html | 1957 ------------------ doc/paper/src/abstract.sgml | 38 - doc/paper/src/acknowl.sgml | 10 - doc/paper/src/body.sgml | 41 - doc/paper/src/codegeneration.sgml | 96 - doc/paper/src/example.sgml | 294 --- doc/paper/src/introduction.sgml | 375 ---- doc/paper/src/lambda.sgml | 142 -- doc/paper/src/metafunctions.sgml | 282 --- doc/paper/src/references.sgml | 247 --- doc/paper/src/sequences.sgml | 566 ----- doc/paper/src/typeselection.sgml | 242 --- doc/paper/src/usage.sgml | 8 - doc/readme | 18 - doc/ref/Forward_Sequence.html | 10 - doc/ref/Integral_Constant.html | 10 - doc/ref/Metafunction.html | 10 - doc/ref/Sequence.html | 10 - doc/ref/Sequences.html | 10 - doc/refmanual.html | 49 + doc/refmanual/accumulate.html | 123 ++ doc/refmanual/acknowledgements.html | 24 + doc/refmanual/advance.html | 138 ++ doc/refmanual/algorithms-concepts.html | 26 + doc/refmanual/algorithms.html | 59 + doc/refmanual/always.html | 108 + doc/refmanual/and.html | 126 ++ doc/refmanual/apply-wrap.html | 151 ++ doc/refmanual/apply.html | 137 ++ doc/refmanual/arg.html | 113 + doc/refmanual/arithmetic-operations.html | 31 + doc/refmanual/assert-msg.html | 152 ++ doc/refmanual/assert-not.html | 111 + doc/refmanual/assert-relation.html | 120 ++ doc/refmanual/assert.html | 111 + doc/refmanual/asserts.html | 33 + doc/refmanual/associative-sequence.html | 156 ++ doc/refmanual/at-c.html | 132 ++ doc/refmanual/at.html | 211 ++ doc/refmanual/aux-lambda-support.html | 120 ++ doc/refmanual/back-extensible-sequence.html | 104 + doc/refmanual/back-inserter.html | 117 ++ doc/refmanual/back.html | 114 + doc/refmanual/begin.html | 114 + doc/refmanual/bidirectional-iterator.html | 107 + doc/refmanual/bidirectional-sequence.html | 96 + doc/refmanual/bind.html | 224 ++ doc/refmanual/bitand.html | 149 ++ doc/refmanual/bitor.html | 149 ++ doc/refmanual/bitwise-operations.html | 30 + doc/refmanual/bitxor.html | 150 ++ doc/refmanual/bool.html | 112 + doc/refmanual/broken-compiler.html | 25 + doc/refmanual/categorized-concepts.html | 46 + doc/refmanual/categorized-index.html | 25 + doc/refmanual/cfg-no-has-xxx.html | 40 + doc/refmanual/cfg-no-preprocessed.html | 46 + doc/refmanual/classes.html | 38 + doc/refmanual/clear.html | 112 + doc/refmanual/comparisons.html | 31 + doc/refmanual/components.html | 173 ++ doc/refmanual/composition-and-argument.html | 31 + doc/refmanual/concepts.html | 57 + doc/refmanual/configuration.html | 33 + doc/refmanual/contains.html | 112 + doc/refmanual/copy-if.html | 142 ++ doc/refmanual/copy.html | 123 ++ doc/refmanual/count-if.html | 116 ++ doc/refmanual/count.html | 110 + doc/refmanual/data-concepts.html | 25 + doc/refmanual/data-miscellaneous.html | 27 + doc/refmanual/data-types.html | 27 + doc/refmanual/deque.html | 63 + doc/refmanual/deref.html | 109 + doc/refmanual/distance.html | 124 ++ doc/refmanual/divides.html | 144 ++ doc/refmanual/empty-base.html | 44 + doc/refmanual/empty-sequence.html | 89 + doc/refmanual/empty.html | 109 + doc/refmanual/end.html | 111 + doc/refmanual/equal-to.html | 132 ++ doc/refmanual/equal.html | 112 + doc/refmanual/erase-key.html | 116 ++ doc/refmanual/erase.html | 193 ++ doc/refmanual/eval-if-c.html | 105 + doc/refmanual/eval-if.html | 106 + doc/refmanual/extensible-associative.html | 131 ++ doc/refmanual/extensible-sequence.html | 125 ++ doc/refmanual/filter-view.html | 129 ++ doc/refmanual/find-if.html | 113 + doc/refmanual/find.html | 111 + doc/refmanual/fold.html | 123 ++ doc/refmanual/forward-iterator.html | 147 ++ doc/refmanual/forward-sequence.html | 136 ++ doc/refmanual/front-extensible-sequence.html | 104 + doc/refmanual/front-inserter.html | 117 ++ doc/refmanual/front.html | 114 + doc/refmanual/greater-equal.html | 132 ++ doc/refmanual/greater.html | 132 ++ doc/refmanual/has-key.html | 113 + doc/refmanual/has-xxx-trait-def.html | 134 ++ doc/refmanual/has-xxx-trait-named-def.html | 180 ++ doc/refmanual/identity.html | 108 + doc/refmanual/if-c.html | 106 + doc/refmanual/if.html | 105 + doc/refmanual/inherit-linearly.html | 152 ++ doc/refmanual/inherit.html | 205 ++ doc/refmanual/insert-range.html | 139 ++ doc/refmanual/insert.html | 214 ++ doc/refmanual/inserter.html | 107 + doc/refmanual/inserters-inserter.html | 122 ++ doc/refmanual/inserters.html | 27 + doc/refmanual/int.html | 112 + doc/refmanual/integral-c.html | 115 + doc/refmanual/integral-constant.html | 121 ++ doc/refmanual/integral-sequence-wrapper.html | 153 ++ doc/refmanual/intrinsic-metafunctions.html | 64 + doc/refmanual/introspection.html | 26 + doc/refmanual/invocation.html | 28 + doc/refmanual/is-sequence.html | 113 + doc/refmanual/iter-fold.html | 133 ++ doc/refmanual/iteration-algorithms.html | 47 + doc/refmanual/iterator-category.html | 130 ++ doc/refmanual/iterator-metafunctions.html | 30 + doc/refmanual/iterator-range.html | 122 ++ doc/refmanual/iterators-concepts.html | 43 + doc/refmanual/iterators.html | 35 + doc/refmanual/joint-view.html | 125 ++ doc/refmanual/key-type.html | 117 ++ doc/refmanual/lambda-expression.html | 51 + doc/refmanual/lambda.html | 146 ++ doc/refmanual/less-equal.html | 132 ++ doc/refmanual/less.html | 132 ++ doc/refmanual/limit-list-size.html | 62 + doc/refmanual/limit-map-size.html | 69 + doc/refmanual/limit-metafunction-arity.html | 72 + doc/refmanual/limit-set-size.html | 62 + doc/refmanual/limit-unrolling.html | 52 + doc/refmanual/limit-vector-size.html | 62 + doc/refmanual/list-c.html | 123 ++ doc/refmanual/list.html | 161 ++ doc/refmanual/logical-operations.html | 28 + doc/refmanual/long.html | 112 + doc/refmanual/lower-bound.html | 125 ++ doc/refmanual/macros.html | 49 + doc/refmanual/manual.png | Bin 0 -> 1732 bytes doc/refmanual/map.html | 183 ++ doc/refmanual/max-element.html | 114 + doc/refmanual/max.html | 115 + doc/refmanual/metafunction-class.html | 121 ++ doc/refmanual/metafunction.html | 127 ++ doc/refmanual/metafunctions-concepts.html | 31 + doc/refmanual/metafunctions.html | 82 + doc/refmanual/min-element.html | 114 + doc/refmanual/min.html | 115 + doc/refmanual/minus.html | 140 ++ doc/refmanual/miscellaneous.html | 32 + doc/refmanual/modulus.html | 139 ++ doc/refmanual/negate.html | 130 ++ doc/refmanual/next.html | 115 + doc/refmanual/not-equal-to.html | 131 ++ doc/refmanual/not.html | 117 ++ doc/refmanual/numeric-cast.html | 149 ++ doc/refmanual/numeric-metafunction.html | 171 ++ doc/refmanual/numeric.html | 29 + doc/refmanual/or.html | 126 ++ doc/refmanual/order.html | 113 + doc/refmanual/pair.html | 74 + doc/refmanual/partition.html | 136 ++ doc/refmanual/placeholder-expression.html | 55 + doc/refmanual/placeholders.html | 99 + doc/refmanual/plus.html | 140 ++ doc/refmanual/pop-back.html | 120 ++ doc/refmanual/pop-front.html | 120 ++ doc/refmanual/prior.html | 115 + doc/refmanual/protect.html | 127 ++ doc/refmanual/push-back.html | 126 ++ doc/refmanual/push-front.html | 125 ++ doc/refmanual/querying-algorithms.html | 35 + doc/refmanual/quote.html | 156 ++ doc/refmanual/random-access-iterator.html | 113 + doc/refmanual/random-access-sequence.html | 98 + doc/refmanual/range-c.html | 144 ++ doc/refmanual/refmanual_toc.html | 302 +++ doc/refmanual/remove-if.html | 140 ++ doc/refmanual/remove.html | 128 ++ doc/refmanual/replace-if.html | 133 ++ doc/refmanual/replace.html | 132 ++ doc/refmanual/reverse-copy-if.html | 142 ++ doc/refmanual/reverse-copy.html | 123 ++ doc/refmanual/reverse-fold.html | 169 ++ doc/refmanual/reverse-iter-fold.html | 169 ++ doc/refmanual/reverse-partition.html | 136 ++ doc/refmanual/reverse-remove-if.html | 139 ++ doc/refmanual/reverse-remove.html | 127 ++ doc/refmanual/reverse-replace-if.html | 138 ++ doc/refmanual/reverse-replace.html | 132 ++ doc/refmanual/reverse-stable-partition.html | 148 ++ doc/refmanual/reverse-transform.html | 184 ++ doc/refmanual/reverse-unique.html | 149 ++ doc/refmanual/reverse.html | 114 + doc/refmanual/reversible-algorithm.html | 188 ++ doc/refmanual/sequence-tag.html | 93 + doc/refmanual/sequences.html | 44 + doc/refmanual/set-c.html | 124 ++ doc/refmanual/set.html | 179 ++ doc/refmanual/shift-left.html | 146 ++ doc/refmanual/shift-right.html | 145 ++ doc/refmanual/single-view.html | 123 ++ doc/refmanual/size-t.html | 112 + doc/refmanual/size.html | 120 ++ doc/refmanual/sizeof.html | 113 + doc/refmanual/sort.html | 151 ++ doc/refmanual/stable-partition.html | 149 ++ doc/refmanual/tag-dispatched.html | 171 ++ doc/refmanual/terminology.html | 51 + doc/refmanual/times.html | 140 ++ doc/refmanual/transform-view.html | 130 ++ doc/refmanual/transform.html | 183 ++ doc/refmanual/transformation-algorithms.html | 62 + doc/refmanual/trivial-metafunction.html | 84 + doc/refmanual/trivial-metafunctions.html | 49 + doc/refmanual/trivial.html | 33 + doc/refmanual/type-selection.html | 29 + doc/refmanual/unique.html | 148 ++ doc/refmanual/unpack-args.html | 110 + doc/refmanual/upper-bound.html | 125 ++ doc/refmanual/value-type.html | 125 ++ doc/refmanual/variadic-sequence.html | 135 ++ doc/refmanual/vector-c.html | 125 ++ doc/refmanual/vector.html | 183 ++ doc/refmanual/views.html | 40 + doc/refmanual/void.html | 51 + doc/refmanual/zip-view.html | 137 ++ doc/src/acknw.sgml | 18 - doc/src/apply_if.sgml | 130 -- doc/src/apply_if2.sgml | 55 - doc/src/articleinfo.sgml | 2 - doc/src/bibliography.sgml | 69 - doc/src/body.sgml | 37 - doc/src/howtos.sgml | 58 - doc/src/if.sgml | 66 - doc/src/lambda.sgml | 30 - doc/src/metafunctions.sgml | 37 - doc/src/preface.sgml | 49 - doc/src/sequences.sgml | 30 - doc/src/technical.sgml | 52 - doc/src/tutorial.sgml | 29 - doc/style.css | 720 +++++++ doc/tidy_attr.py | 28 - doc/tidy_config | 7 - doc/tutorial/acknowledgements.html | 38 + doc/tutorial/apply-lambda-semantics.html | 91 + doc/tutorial/book_cover.png | Bin 0 -> 39700 bytes doc/tutorial/broken-integral-constant.html | 116 ++ doc/tutorial/changelog-history.html | 24 + doc/tutorial/changes-in-boost-1-32-0.html | 34 + doc/tutorial/dependencies.html | 32 + doc/tutorial/details.html | 119 ++ doc/tutorial/dimensional-analysis.html | 85 + doc/tutorial/eti.html | 119 ++ doc/tutorial/exercises.html | 103 + doc/tutorial/handling-placeholders.html | 60 + doc/tutorial/higher-order.html | 141 ++ doc/tutorial/implementing-addition-and.html | 56 + doc/tutorial/implementing-division.html | 163 ++ doc/tutorial/implementing.html | 265 +++ doc/tutorial/incomplete-support-for.html | 126 ++ doc/tutorial/iterator-protocol.html | 56 + doc/tutorial/lambda-and-non.html | 47 + doc/tutorial/lambda-details.html | 30 + doc/tutorial/metafunction-composition.html | 39 + doc/tutorial/miscellaneous.html | 35 + doc/tutorial/more-lambda-capabilities.html | 29 + doc/tutorial/numeric-metafunction.html | 71 + doc/tutorial/partial-metafunction.html | 41 + doc/tutorial/physical-structure.html | 32 + doc/tutorial/placeholder-expression.html | 97 + doc/tutorial/placeholders.html | 162 ++ doc/tutorial/portability.html | 135 ++ doc/tutorial/reference-manual.html | 28 + doc/tutorial/renaming-cleanup.html | 78 + doc/tutorial/representing-dimensions.html | 153 ++ doc/tutorial/representing-quantities.html | 55 + doc/tutorial/resources.html | 49 + doc/tutorial/tag-dispatching-protocol.html | 75 + doc/tutorial/technical-details.html | 28 + doc/tutorial/the-apply-metafunction.html | 76 + doc/tutorial/the-importance-of-being.html | 55 + doc/tutorial/the-lambda-metafunction.html | 85 + doc/tutorial/tutorial-metafunctions.html | 47 + doc/tutorial/tutorial_toc.html | 77 + 306 files changed, 27492 insertions(+), 7633 deletions(-) delete mode 100644 doc/article.css delete mode 100755 doc/msxsl_build.bat delete mode 100644 doc/paper/article.css delete mode 100644 doc/paper/html/acknowl.html delete mode 100644 doc/paper/html/article.css delete mode 100644 doc/paper/html/codegeneration.html delete mode 100644 doc/paper/html/example.html delete mode 100644 doc/paper/html/index.html delete mode 100644 doc/paper/html/intro.html delete mode 100644 doc/paper/html/lambda.html delete mode 100644 doc/paper/html/refs.html delete mode 100644 doc/paper/html/usage.html delete mode 100755 doc/paper/html/xsltproc_build.bat delete mode 100644 doc/paper/mpl_paper.html delete mode 100644 doc/paper/src/abstract.sgml delete mode 100644 doc/paper/src/acknowl.sgml delete mode 100644 doc/paper/src/body.sgml delete mode 100644 doc/paper/src/codegeneration.sgml delete mode 100644 doc/paper/src/example.sgml delete mode 100644 doc/paper/src/introduction.sgml delete mode 100644 doc/paper/src/lambda.sgml delete mode 100644 doc/paper/src/metafunctions.sgml delete mode 100644 doc/paper/src/references.sgml delete mode 100644 doc/paper/src/sequences.sgml delete mode 100644 doc/paper/src/typeselection.sgml delete mode 100644 doc/paper/src/usage.sgml delete mode 100644 doc/readme delete mode 100644 doc/ref/Forward_Sequence.html delete mode 100644 doc/ref/Integral_Constant.html delete mode 100644 doc/ref/Metafunction.html delete mode 100644 doc/ref/Sequence.html delete mode 100644 doc/ref/Sequences.html create mode 100644 doc/refmanual.html create mode 100644 doc/refmanual/accumulate.html create mode 100644 doc/refmanual/acknowledgements.html create mode 100644 doc/refmanual/advance.html create mode 100644 doc/refmanual/algorithms-concepts.html create mode 100644 doc/refmanual/algorithms.html create mode 100644 doc/refmanual/always.html create mode 100644 doc/refmanual/and.html create mode 100644 doc/refmanual/apply-wrap.html create mode 100644 doc/refmanual/apply.html create mode 100644 doc/refmanual/arg.html create mode 100644 doc/refmanual/arithmetic-operations.html create mode 100644 doc/refmanual/assert-msg.html create mode 100644 doc/refmanual/assert-not.html create mode 100644 doc/refmanual/assert-relation.html create mode 100644 doc/refmanual/assert.html create mode 100644 doc/refmanual/asserts.html create mode 100644 doc/refmanual/associative-sequence.html create mode 100644 doc/refmanual/at-c.html create mode 100644 doc/refmanual/at.html create mode 100644 doc/refmanual/aux-lambda-support.html create mode 100644 doc/refmanual/back-extensible-sequence.html create mode 100644 doc/refmanual/back-inserter.html create mode 100644 doc/refmanual/back.html create mode 100644 doc/refmanual/begin.html create mode 100644 doc/refmanual/bidirectional-iterator.html create mode 100644 doc/refmanual/bidirectional-sequence.html create mode 100644 doc/refmanual/bind.html create mode 100644 doc/refmanual/bitand.html create mode 100644 doc/refmanual/bitor.html create mode 100644 doc/refmanual/bitwise-operations.html create mode 100644 doc/refmanual/bitxor.html create mode 100644 doc/refmanual/bool.html create mode 100644 doc/refmanual/broken-compiler.html create mode 100644 doc/refmanual/categorized-concepts.html create mode 100644 doc/refmanual/categorized-index.html create mode 100644 doc/refmanual/cfg-no-has-xxx.html create mode 100644 doc/refmanual/cfg-no-preprocessed.html create mode 100644 doc/refmanual/classes.html create mode 100644 doc/refmanual/clear.html create mode 100644 doc/refmanual/comparisons.html create mode 100644 doc/refmanual/components.html create mode 100644 doc/refmanual/composition-and-argument.html create mode 100644 doc/refmanual/concepts.html create mode 100644 doc/refmanual/configuration.html create mode 100644 doc/refmanual/contains.html create mode 100644 doc/refmanual/copy-if.html create mode 100644 doc/refmanual/copy.html create mode 100644 doc/refmanual/count-if.html create mode 100644 doc/refmanual/count.html create mode 100644 doc/refmanual/data-concepts.html create mode 100644 doc/refmanual/data-miscellaneous.html create mode 100644 doc/refmanual/data-types.html create mode 100644 doc/refmanual/deque.html create mode 100644 doc/refmanual/deref.html create mode 100644 doc/refmanual/distance.html create mode 100644 doc/refmanual/divides.html create mode 100644 doc/refmanual/empty-base.html create mode 100644 doc/refmanual/empty-sequence.html create mode 100644 doc/refmanual/empty.html create mode 100644 doc/refmanual/end.html create mode 100644 doc/refmanual/equal-to.html create mode 100644 doc/refmanual/equal.html create mode 100644 doc/refmanual/erase-key.html create mode 100644 doc/refmanual/erase.html create mode 100644 doc/refmanual/eval-if-c.html create mode 100644 doc/refmanual/eval-if.html create mode 100644 doc/refmanual/extensible-associative.html create mode 100644 doc/refmanual/extensible-sequence.html create mode 100644 doc/refmanual/filter-view.html create mode 100644 doc/refmanual/find-if.html create mode 100644 doc/refmanual/find.html create mode 100644 doc/refmanual/fold.html create mode 100644 doc/refmanual/forward-iterator.html create mode 100644 doc/refmanual/forward-sequence.html create mode 100644 doc/refmanual/front-extensible-sequence.html create mode 100644 doc/refmanual/front-inserter.html create mode 100644 doc/refmanual/front.html create mode 100644 doc/refmanual/greater-equal.html create mode 100644 doc/refmanual/greater.html create mode 100644 doc/refmanual/has-key.html create mode 100644 doc/refmanual/has-xxx-trait-def.html create mode 100644 doc/refmanual/has-xxx-trait-named-def.html create mode 100644 doc/refmanual/identity.html create mode 100644 doc/refmanual/if-c.html create mode 100644 doc/refmanual/if.html create mode 100644 doc/refmanual/inherit-linearly.html create mode 100644 doc/refmanual/inherit.html create mode 100644 doc/refmanual/insert-range.html create mode 100644 doc/refmanual/insert.html create mode 100644 doc/refmanual/inserter.html create mode 100644 doc/refmanual/inserters-inserter.html create mode 100644 doc/refmanual/inserters.html create mode 100644 doc/refmanual/int.html create mode 100644 doc/refmanual/integral-c.html create mode 100644 doc/refmanual/integral-constant.html create mode 100644 doc/refmanual/integral-sequence-wrapper.html create mode 100644 doc/refmanual/intrinsic-metafunctions.html create mode 100644 doc/refmanual/introspection.html create mode 100644 doc/refmanual/invocation.html create mode 100644 doc/refmanual/is-sequence.html create mode 100644 doc/refmanual/iter-fold.html create mode 100644 doc/refmanual/iteration-algorithms.html create mode 100644 doc/refmanual/iterator-category.html create mode 100644 doc/refmanual/iterator-metafunctions.html create mode 100644 doc/refmanual/iterator-range.html create mode 100644 doc/refmanual/iterators-concepts.html create mode 100644 doc/refmanual/iterators.html create mode 100644 doc/refmanual/joint-view.html create mode 100644 doc/refmanual/key-type.html create mode 100644 doc/refmanual/lambda-expression.html create mode 100644 doc/refmanual/lambda.html create mode 100644 doc/refmanual/less-equal.html create mode 100644 doc/refmanual/less.html create mode 100644 doc/refmanual/limit-list-size.html create mode 100644 doc/refmanual/limit-map-size.html create mode 100644 doc/refmanual/limit-metafunction-arity.html create mode 100644 doc/refmanual/limit-set-size.html create mode 100644 doc/refmanual/limit-unrolling.html create mode 100644 doc/refmanual/limit-vector-size.html create mode 100644 doc/refmanual/list-c.html create mode 100644 doc/refmanual/list.html create mode 100644 doc/refmanual/logical-operations.html create mode 100644 doc/refmanual/long.html create mode 100644 doc/refmanual/lower-bound.html create mode 100644 doc/refmanual/macros.html create mode 100644 doc/refmanual/manual.png create mode 100644 doc/refmanual/map.html create mode 100644 doc/refmanual/max-element.html create mode 100644 doc/refmanual/max.html create mode 100644 doc/refmanual/metafunction-class.html create mode 100644 doc/refmanual/metafunction.html create mode 100644 doc/refmanual/metafunctions-concepts.html create mode 100644 doc/refmanual/metafunctions.html create mode 100644 doc/refmanual/min-element.html create mode 100644 doc/refmanual/min.html create mode 100644 doc/refmanual/minus.html create mode 100644 doc/refmanual/miscellaneous.html create mode 100644 doc/refmanual/modulus.html create mode 100644 doc/refmanual/negate.html create mode 100644 doc/refmanual/next.html create mode 100644 doc/refmanual/not-equal-to.html create mode 100644 doc/refmanual/not.html create mode 100644 doc/refmanual/numeric-cast.html create mode 100644 doc/refmanual/numeric-metafunction.html create mode 100644 doc/refmanual/numeric.html create mode 100644 doc/refmanual/or.html create mode 100644 doc/refmanual/order.html create mode 100644 doc/refmanual/pair.html create mode 100644 doc/refmanual/partition.html create mode 100644 doc/refmanual/placeholder-expression.html create mode 100644 doc/refmanual/placeholders.html create mode 100644 doc/refmanual/plus.html create mode 100644 doc/refmanual/pop-back.html create mode 100644 doc/refmanual/pop-front.html create mode 100644 doc/refmanual/prior.html create mode 100644 doc/refmanual/protect.html create mode 100644 doc/refmanual/push-back.html create mode 100644 doc/refmanual/push-front.html create mode 100644 doc/refmanual/querying-algorithms.html create mode 100644 doc/refmanual/quote.html create mode 100644 doc/refmanual/random-access-iterator.html create mode 100644 doc/refmanual/random-access-sequence.html create mode 100644 doc/refmanual/range-c.html create mode 100644 doc/refmanual/refmanual_toc.html create mode 100644 doc/refmanual/remove-if.html create mode 100644 doc/refmanual/remove.html create mode 100644 doc/refmanual/replace-if.html create mode 100644 doc/refmanual/replace.html create mode 100644 doc/refmanual/reverse-copy-if.html create mode 100644 doc/refmanual/reverse-copy.html create mode 100644 doc/refmanual/reverse-fold.html create mode 100644 doc/refmanual/reverse-iter-fold.html create mode 100644 doc/refmanual/reverse-partition.html create mode 100644 doc/refmanual/reverse-remove-if.html create mode 100644 doc/refmanual/reverse-remove.html create mode 100644 doc/refmanual/reverse-replace-if.html create mode 100644 doc/refmanual/reverse-replace.html create mode 100644 doc/refmanual/reverse-stable-partition.html create mode 100644 doc/refmanual/reverse-transform.html create mode 100644 doc/refmanual/reverse-unique.html create mode 100644 doc/refmanual/reverse.html create mode 100644 doc/refmanual/reversible-algorithm.html create mode 100644 doc/refmanual/sequence-tag.html create mode 100644 doc/refmanual/sequences.html create mode 100644 doc/refmanual/set-c.html create mode 100644 doc/refmanual/set.html create mode 100644 doc/refmanual/shift-left.html create mode 100644 doc/refmanual/shift-right.html create mode 100644 doc/refmanual/single-view.html create mode 100644 doc/refmanual/size-t.html create mode 100644 doc/refmanual/size.html create mode 100644 doc/refmanual/sizeof.html create mode 100644 doc/refmanual/sort.html create mode 100644 doc/refmanual/stable-partition.html create mode 100644 doc/refmanual/tag-dispatched.html create mode 100644 doc/refmanual/terminology.html create mode 100644 doc/refmanual/times.html create mode 100644 doc/refmanual/transform-view.html create mode 100644 doc/refmanual/transform.html create mode 100644 doc/refmanual/transformation-algorithms.html create mode 100644 doc/refmanual/trivial-metafunction.html create mode 100644 doc/refmanual/trivial-metafunctions.html create mode 100644 doc/refmanual/trivial.html create mode 100644 doc/refmanual/type-selection.html create mode 100644 doc/refmanual/unique.html create mode 100644 doc/refmanual/unpack-args.html create mode 100644 doc/refmanual/upper-bound.html create mode 100644 doc/refmanual/value-type.html create mode 100644 doc/refmanual/variadic-sequence.html create mode 100644 doc/refmanual/vector-c.html create mode 100644 doc/refmanual/vector.html create mode 100644 doc/refmanual/views.html create mode 100644 doc/refmanual/void.html create mode 100644 doc/refmanual/zip-view.html delete mode 100644 doc/src/acknw.sgml delete mode 100644 doc/src/apply_if.sgml delete mode 100644 doc/src/apply_if2.sgml delete mode 100644 doc/src/articleinfo.sgml delete mode 100644 doc/src/bibliography.sgml delete mode 100644 doc/src/body.sgml delete mode 100644 doc/src/howtos.sgml delete mode 100644 doc/src/if.sgml delete mode 100644 doc/src/lambda.sgml delete mode 100644 doc/src/metafunctions.sgml delete mode 100644 doc/src/preface.sgml delete mode 100644 doc/src/sequences.sgml delete mode 100644 doc/src/technical.sgml delete mode 100644 doc/src/tutorial.sgml create mode 100644 doc/style.css delete mode 100644 doc/tidy_attr.py delete mode 100644 doc/tidy_config create mode 100644 doc/tutorial/acknowledgements.html create mode 100644 doc/tutorial/apply-lambda-semantics.html create mode 100644 doc/tutorial/book_cover.png create mode 100644 doc/tutorial/broken-integral-constant.html create mode 100644 doc/tutorial/changelog-history.html create mode 100644 doc/tutorial/changes-in-boost-1-32-0.html create mode 100644 doc/tutorial/dependencies.html create mode 100644 doc/tutorial/details.html create mode 100644 doc/tutorial/dimensional-analysis.html create mode 100644 doc/tutorial/eti.html create mode 100644 doc/tutorial/exercises.html create mode 100644 doc/tutorial/handling-placeholders.html create mode 100644 doc/tutorial/higher-order.html create mode 100644 doc/tutorial/implementing-addition-and.html create mode 100644 doc/tutorial/implementing-division.html create mode 100644 doc/tutorial/implementing.html create mode 100644 doc/tutorial/incomplete-support-for.html create mode 100644 doc/tutorial/iterator-protocol.html create mode 100644 doc/tutorial/lambda-and-non.html create mode 100644 doc/tutorial/lambda-details.html create mode 100644 doc/tutorial/metafunction-composition.html create mode 100644 doc/tutorial/miscellaneous.html create mode 100644 doc/tutorial/more-lambda-capabilities.html create mode 100644 doc/tutorial/numeric-metafunction.html create mode 100644 doc/tutorial/partial-metafunction.html create mode 100644 doc/tutorial/physical-structure.html create mode 100644 doc/tutorial/placeholder-expression.html create mode 100644 doc/tutorial/placeholders.html create mode 100644 doc/tutorial/portability.html create mode 100644 doc/tutorial/reference-manual.html create mode 100644 doc/tutorial/renaming-cleanup.html create mode 100644 doc/tutorial/representing-dimensions.html create mode 100644 doc/tutorial/representing-quantities.html create mode 100644 doc/tutorial/resources.html create mode 100644 doc/tutorial/tag-dispatching-protocol.html create mode 100644 doc/tutorial/technical-details.html create mode 100644 doc/tutorial/the-apply-metafunction.html create mode 100644 doc/tutorial/the-importance-of-being.html create mode 100644 doc/tutorial/the-lambda-metafunction.html create mode 100644 doc/tutorial/tutorial-metafunctions.html create mode 100644 doc/tutorial/tutorial_toc.html diff --git a/doc/article.css b/doc/article.css deleted file mode 100644 index 7dc14de..0000000 --- a/doc/article.css +++ /dev/null @@ -1,67 +0,0 @@ -div.articletitle -{ - text-align: center; - text-transform: uppercase; -} - -div.authorgroup -{ - text-align: center; -} - -h3.title span.emphasis em -{ - font-style: normal; - text-decoration: underline; -} - -body -{ - background-color: white; - color: black; -} - -sup -{ - font-size: x-small; - font-weight: lighter; -} - -a:link, -a:visited -{ - color: #505050; -} - - sup a:link -,sup a:visited -,a.interlink:link -,a.interlink:visited -{ - color: #505050; - text-decoration: none; -} - -div.biblioentry p -{ - border-style: none none none solid; - border-width: 1px; - border-color: silver; - margin-top: -1em; - padding-left: 0.5em; - padding-top: 0.25em; -} - -div.footnote p -{ - margin-bottom: -0.5em; -} - -pre.programlisting -{ - - border-style: none none none solid; - border-width: 1px; - border-color: silver; - padding-left: 1em; -} diff --git a/doc/index.html b/doc/index.html index 2b5aad8..05ea5b9 100644 --- a/doc/index.html +++ b/doc/index.html @@ -1,29 +1,75 @@ - - + + + - - THE BOOST MPL LIBRARY - - + + +THE BOOST MPL LIBRARY + + - - -
- -
-
- -
-

THE BOOST MPL LIBRARY

+ + + www.boost.org + +

THE BOOST MPL LIBRARY

+ +++ + + + + + +
Copyright:Copyright © Aleksey Gurtovoy and David Abrahams, 2002-2004.
License:Distributed under the Boost Software License, Version 1.0. (See +accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt)
+
+

The Boost.MPL library is a general-purpose, high-level C++ +template metaprogramming framework of compile-time algorithms, sequences and +metafunctions. It provides a conceptual foundation and an extensive +set of powerful and coherent tools that make doing explict metaprogramming +in C++ as easy and enjoyable as possible within the current language.

+

There are several places to start when getting familiar with the library, +depending on what your know about metaprogramming in general and +C++ template metaprogramming in particular. Starting with +Boost version 1.32, the MPL comes with both an in-depth tutorial on its +fundamental concepts and an annotated reference manual covering all concepts +and components in the library. While the tutorial +only uncovers a bit of what there is to C++ metaprogramming and the MPL, +it's a perfect place to start if you are only somewhat familiar with the +subject. At the very least, after you're done with it, you will be able to put +the rest of the stuff that appears here into context. The reference manual +is the resource for you if you plan — or are already doing — some actual +development with the library, but a casual reading is still allowed and likely +to bring many insights on the framework's organization and underlying +ideas. Finally, the top-level sections in this document that you +see highlighted below might also offer something of interest.

+

So, welcome, and happy metaprogramming!

+
+
Important:
+
There have been some major interface changes in the library since the last +public release, many of which are not backward compatible. If you are +a seasoned MPL user, be prepared to have to modify your code after +upgrading. Please refer to the 1.32 release changelog +for the detailed information about the changes.
+
+ +
+ + -
- -

The Boost MPL library documentation is currently undergoing a major overhaul -for the 1.32 release. Please come back in a few days.

- -
- - diff --git a/doc/msxsl_build.bat b/doc/msxsl_build.bat deleted file mode 100755 index 8d5ef47..0000000 --- a/doc/msxsl_build.bat +++ /dev/null @@ -1,15 +0,0 @@ -@echo off - -if "%3" == "" goto usage - -sx -x lower -x empty %2 >%3.xml -msxsl.exe %3.xml ..\..\..\..\..\docbook-xsl-1.50.0\html\my\%1 -o %3 -del %3.xml -tidy.exe -config tidy_config -m %3 -python tidy_attr.py %3 -exit - -:usage -echo Usage examples: -echo msxsl_build.bat docbook_msxsl.xsl src\body.sgml index.html -echo msxsl_build.bat docbook_msxsl.xsl paper\src\body.sgml paper\mpl_paper.html diff --git a/doc/paper/article.css b/doc/paper/article.css deleted file mode 100644 index dc41d0b..0000000 --- a/doc/paper/article.css +++ /dev/null @@ -1,87 +0,0 @@ -div.articletitle -{ - text-align: center; - text-transform: uppercase; -} - -div.authorgroup -{ - text-align: center; -} - -h3.title span.emphasis em -{ - font-style: normal; - text-decoration: underline; -} - -body -{ - background-color: white; - color: black; -} - -sup -{ - font-size: x-small; - font-weight: lighter; -} - -a:link -,a:visited -{ - color: #505050; -} - - sup a:link -,sup a:visited -,a.interlink:link -,a.interlink:visited -{ - color: #505050; - text-decoration: none; -} - -div.biblioentry p -{ - border-style: none none none solid; - border-width: 1px; - border-color: silver; - margin-top: -1em; - padding-left: 0.5em; - padding-top: 0.25em; -} - -div.footnote p -{ - margin-bottom: -0.5em; -} - -div.table table -{ - border: solid; - border-width: 1px; - border-color: silver; -} - -div.table table tr th -{ - background-color: #f0f0f0; - padding-left: 1em; - padding-right: 1em; -} - -div.table table tr td -{ - padding-left: 1em; - padding-right: 1em; -} - -pre.programlisting -{ - - border-style: none none none solid; - border-width: 1px; - border-color: silver; - padding-left: 1em; -} diff --git a/doc/paper/html/acknowl.html b/doc/paper/html/acknowl.html deleted file mode 100644 index 16f7a65..0000000 --- a/doc/paper/html/acknowl.html +++ /dev/null @@ -1,59 +0,0 @@ - - - - -6. Acknowledgements - - - - - - - - - - - -
-
-
-

6. Acknowledgements

-
-
- -

Peter Dimov contributed the bind functionality without which compile-time lambda expressions wouldn't have been possible. The MPL implementation would have been much more difficult without Vesa Karvonen's wonderful Boost Preprocessor Metaprogramming Library. Authors are also greatly indebted to David B. Held who kindly volunteered to thoroughly edit this document. Of course, any remaining errors are exclusively ours.

-
- - - - - diff --git a/doc/paper/html/article.css b/doc/paper/html/article.css deleted file mode 100644 index 7c183ea..0000000 --- a/doc/paper/html/article.css +++ /dev/null @@ -1,82 +0,0 @@ -div.articletitle -{ - text-align: center; - text-transform: uppercase; -} - -div.authorgroup -{ - text-align: center; -} - -h3.title span.emphasis em -{ - font-style: normal; - text-decoration: underline; -} - -body -{ - background-color: white; - color: black; -} - -sup -{ - font-size: x-small; - font-weight: lighter; -} - -a:link -,a:visited -{ - color: #505050; -} - - sup a:link -,sup a:visited -,a.interlink:link -,a.interlink:visited -{ - color: #505050; - text-decoration: none; -} - -div.biblioentry p -{ - border-style: none none none solid; - border-width: 1px; - border-color: silver; - margin-top: -1em; - padding-left: 0.5em; - padding-top: 0.25em; -} - -div.table table -{ - border: solid; - border-width: 1px; - border-color: silver; -} - -div.table table tr th -{ - background-color: #f0f0f0; - padding-left: 1em; - padding-right: 1em; -} - -div.table table tr td -{ - padding-left: 1em; - padding-right: 1em; -} - -pre.programlisting -{ - - border-style: none none none solid; - border-width: 1px; - border-color: silver; - padding-left: 1em; -} diff --git a/doc/paper/html/codegeneration.html b/doc/paper/html/codegeneration.html deleted file mode 100644 index ca0e68f..0000000 --- a/doc/paper/html/codegeneration.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - -4. Code generation facilities - - - - - - - - - - - -
-
-
-

4. Code generation facilities

-
-
- -

There are cases, especially in the domain of numeric computation, when one wants to perform some part of the calculations at compile-time, and then pass the results to a run-time part of the program for further processing. For example, suppose one has implemented a complex compile-time algorithm that works with fixed-point arithmetic:

- -
-// fixed-point algorithm input
-typedef mpl::vector<
-      mpl::fixed_c<-1,2345678>
-    , mpl::fixed_c<9,0001>
-    // ..
-    , mpl::fixed_c<3,14159>
-    > input_data;
-
-/*
-  complex compile-time algorithm 
-*/
-typedef /*...*/ result_data;
-
- -

Suppose the result_data here is a sequence of mpl::fixed_c types that keeps the results of the algorithm, and now one wishes to feed that result to the run-time part of the algorithm. With MPL she can do this:

- -
-double my_algorithm()
-{
-    // passing the results to the run-time part of the program
-    std::vector<double> results;
-    results.reserve(mpl::size<result_data>::value);
-    mpl::for_each<numbers,_>(
-          boost::bind(&std::vector<double>::push_back, &results, _1)
-        );
-    // ...
-}
-
- -

The for_each<numbers,_>(...) call is what actually transfers the compile-time result_data into run-time results. for_each is a function template declared as:

- -
-template<
-      typename Seq
-    , typename TransformOp
-    , typename F
-    >
-void for_each(F f)
-{
-    // ...
-}
-
- -

To call the function, one is required to explicitly provide two actual template parameters, a compile-time sequence Seq and a unary transformation metafunction TransformOp, plus a run-time function argument f (in our example, numbers, _, and boost::bind(...) correspondingly). f is a function object which operator() is called for every element in the Seq tranfromed by TransformOp.

- -

Applying this to our example, the

- -
-mpl::for_each<numbers,_>(
-      boost::bind(&std::vector<double>::push_back, &results, _1)
-    );
-
- -

call is roughly equivalent to this:

- -
-f(mpl::apply< _,mpl::at_c<result_data,0>::type >::type());
-f(mpl::apply< _,mpl::at_c<result_data,1>::type >::type());
-// ...
-f(mpl::apply< _,mpl::at_c<result_data,n>::type >::type());
-
- -

where n == mpl::size<result_data>::type::value.

-
- - - - - diff --git a/doc/paper/html/example.html b/doc/paper/html/example.html deleted file mode 100644 index 356fe10..0000000 --- a/doc/paper/html/example.html +++ /dev/null @@ -1,325 +0,0 @@ - - - - -5. Example: a compile-time FSM generator - - - - - - - - - - - -
-
-
-

5. Example: a compile-time FSM generator

-
-
- -

Finite state machines (FSMs) are an important tool for describing and implementing program behavior [HU79], [Mar98]. They also are a good example of a domain in which metaprogramming can be applied to reduce the amount of repetitive and boilerplate operations one must perform in order to implement these simple mathematical models in code. Below we present a simple state machine generator that has been implemented using Boost Metaprogramming Library facilities. The generator takes a compile-time automata description, and converts it into C++ code that implements the FSM at run-time.

- -

The FSM description is basically a combination of states and events plus a state transition table (STT), which ties them all together. The generator walks through the table and generates the state machine's process_event method that is the essence of an FSM.

- -

Suppose we want to implement a simple music player using a finite state machine model. The state transition table for the FSM is shown in Table 1. The STT format reflects the way one usually describes the behavior of an FSM in plain English. For example, the first line of the table can be read as follows: ‘If the model is in the stopped state and the play_event is received, then the do_play transition function is called, and the model transitions to the playing state’.

- -
- ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
StateEventNext stateTransition function
stoppedplay_eventplayingdo_play
playingstop_eventstoppeddo_stop
playingpause_eventpauseddo_pause
pausedplay_eventplayingdo_resume
pausedstop_eventstoppeddo_stop
- -

Table 1. Player's state transition table with actions

-
- -

The transition table provides us with a complete formal definition of the target FSM, and there are several ways to transform that definition into code. For instance, if we define states as members of an enumeration type, and events as classes derived from some base event class 10 , like so:

- -
-class player
-{
- public:
-    // event declarations
-    struct event;
-    struct play_event;
-    struct stop_event;
-    struct pause_event;
-
-    // "input" function
-    void process_event(event const&); // throws
-
- private:
-    // states
-    enum state_t { stopped, playing, paused };
-
-    // transition functions
-    void do_play(play_event const&);
-    void do_stop(stop_event const&);
-    void do_pause(pause_event const&);
-    void do_resume(play_event const&);
-
- private:
-    state_t m_state;
-};
-
- -

then the most straightforward way to derive the FSM implementation from the above table would be something like this:

- -
-void player::process_event(event const& e)
-{
-    if (m_state == stopped)
-    {
-        if (typeid(e) == typeid(play_event))
-        {
-            do_play(static_cast<play_event const&>(e));
-            m_state = playing;
-            return;
-        }
-    }
-    else if (m_state == playing)
-    {
-        if (typeid(e) == typeid(stop_event))
-        {
-            do_stop(static_cast<stop_event const&>(e));
-            m_state = stopped;
-            return;
-        }
-
-        if (typeid(e) == typeid(pause_event))
-        {
-            do_pause(static_cast<pause_event const&>(e));
-            m_state = paused;
-            return;
-        }
-    }
-    else if (m_state == paused)
-    {
-        if (typeid(e) == typeid(stop_event))
-        {
-            do_stop(static_cast<stop_event const&>(e));
-            m_state = stopped;
-            return;
-        }
-
-        if (typeid(e) == typeid(play_event))
-        {
-            do_play(static_cast<play_event const&>(e));
-            m_state = playing;
-            return;
-        }
-    }
-    else
-    {
-        throw logic_error(
-            boost::format("unknown state: %d")
-                % static_cast<int>(m_state)
-            );
-    }
-
-    throw std::logic_error(
-        "unexpected event: " + typeid(e).name()
-        );
-}
-
- -

Although there is nothing particularly wrong with implementing an FSM's structure using nested if (or switch-case) statements, the obvious weakness of this approach is that most of the above code is boilerplate. What one tends to do with boilerplate code is to copy and paste it, then change names etc. to adjust it to its new location; and that's where the errors are most likely to creep in. Since all the lines of event processing look alike (structurally), it's very easy to overlook or forget something that needs to be changed, and many such errors won't appear until the runtime.

- -

The transition table of our FSM is just five lines long; ideally, we would like the skeleton implementation of the automata's controlling logic to be equally short (or, at least, to look equally short, i.e. to be encapsulated in some form so we never worry about it).

- -
-
-
-

5.1. Implementation

-
-
- -

To represent the STT in a C++ program, we define a transition class template that represents a single line of the table. Then the table itself can be represented as a sequence of such lines:

- -
-typedef mpl::list<
-      transition<stopped, play_event,  playing, &player::do_play>
-    , transition<playing, stop_event,  stopped, &player::do_stop>
-    , transition<playing, pause_event, paused,  &player::do_pause>
-    , transition<paused,  play_event,  playing, &player::do_resume>
-    , transition<paused,  stop_event,  stopped, &player::do_stop>
-    >::type transition_table;
-
- -

Now, the complete FSM will look like this:

- -
-class player
-    : state_machine<player>
-{
- private:
-    typedef player self_t;
-
-    // state invariants
-    void stopped_state_invariant();
-    void playing_state_invariant();
-    void paused_state_invariant();
-
-    // states (invariants are passed as non-type template arguments,
-    // and are called then the FSM enters the corresponding state)
-    typedef state<0, &self_t::stopped_state_invariant> stopped;
-    typedef state<1, &self_t::playing_state_invariant> playing;
-    typedef state<2, &self_t::paused_state_invariant> paused;
-
- private:
-    // event declarations; events are represented as types, 
-    // and can carry a specific data for each event;
-    // but it's not needed for generator, so we define them later
-    struct play_event;
-    struct stop_event;
-    struct pause_event;
-
-    // transition functions
-    void do_play(play_event const&);
-    void do_stop(stop_event const&);
-    void do_pause(pause_event const&);
-    void do_resume(play_event const&);
-
-    // STT
-    friend class state_machine<player>;
-    typedef mpl::list<
-          transition<stopped, play_event,  playing, &player::do_play>
-        , transition<playing, stop_event,  stopped, &player::do_stop>
-        , transition<playing, pause_event, paused,  &player::do_pause>
-        , transition<paused,  play_event,  playing, &player::do_resume>
-        , transition<paused,  stop_event,  stopped, &player::do_stop>
-        >::type transition_table;
-};
-
- -

That's all - the above will generate a complete FSM implementation according to our specification. The only thing we need before using it is the definition of the event types (that were just forward declared before):

- -
-// event definitions
-struct player::play_event
-    : player::event
-{
-};
-
-// ...
-
- -

The usage is simple as well:

- -
-int main()
-{
-    // usage example
-    player p;
-    p.process_event(player::play_event());
-    p.process_event(player::pause_event());
-    p.process_event(player::play_event());
-    p.process_event(player::stop_event());
-    return 0;
-}
-
-
- -
-
-
-

5.2. Related work

-
-
- -

A notable prior work in the field of automation of general-purpose state machine implementation in C++ is the Robert Martin's State Machine Compiler [SMC]. The SMC takes an ASCII description of the machine's state transition table and produces C++ code that implements the FSM using a variation of State design pattern [Hun91], [GHJ+95]. Lafreniere [Laf00] presents another approach, where no external tools are used, and the FSMs are table driven.

-
- -

-
-
-

10The events need to be passed to action functions, as they may contain some event-specific information for an action.

-
-
-
- - - - - diff --git a/doc/paper/html/index.html b/doc/paper/html/index.html deleted file mode 100644 index 0ba8e90..0000000 --- a/doc/paper/html/index.html +++ /dev/null @@ -1,181 +0,0 @@ - - - - -The Boost C++ Metaprogramming Library - - - - - - - - - -
-
-
-
-

The Boost C++ Metaprogramming Library

-
-
- -
-
-

Aleksey Gurtovoyi and David Abrahamsii

- -
iMetaCommunications, agurtovoy@meta-comm.com
- -
iiBoost Consulting, david.abrahams@rcn.com
-
-
- -
-
-

Abstract

- -

This paper describes the Boost C++ template metaprogramming library (MPL), an extensible compile-time framework of algorithms, sequences and metafunction classes. The library brings together important abstractions from the generic and functional programming worlds to build a powerful and easy-to-use toolset which makes template metaprogramming practical enough for the real-world environments. The MPL is heavily influenced by its run-time equivalent - the Standard Template Library (STL), a part of the C++ standard library [STL94], [ISO98]. Like the STL, it defines an open conceptual and implementation framework which can serve as a foundation for future contributions in the domain. The library's fundamental concepts and idioms enable the user to focus on solutions without navigating the universe of possible ad-hoc approaches to a given metaprogramming problem, even if no actual MPL code is used. The library also provides a compile-time lambda expression facility enabling arbitrary currying and composition of class templates, a feature whose runtime counterpart is often cited as missing from the STL. This paper explains the motivation, usage, design, and implementation of the MPL with examples of its real-life applications, and offers some lessons learned about C++ template metaprogramming.

-
-
- -
-
-

Keywords: template metaprogramming, generic programming, programming languages, C++, STL, type systems, polymorphism, compile-time

-
-
-
- - -
- - - - - diff --git a/doc/paper/html/intro.html b/doc/paper/html/intro.html deleted file mode 100644 index 1ad5c03..0000000 --- a/doc/paper/html/intro.html +++ /dev/null @@ -1,359 +0,0 @@ - - - - -1. Introduction - - - - - - - - - - - -
-
-
-

1. Introduction

-
-
- -

Metaprogramming is usually defined as the creation of programs which generate other programs. Parser generators such as YACC [Joh79] are examples of one kind of program-generating program. The input language to YACC is a context-free grammar in Extended Backus-Naur Form [EBNF], and its output is a program which parses that grammar. Note that in this case the metaprogram (YACC) is written in a language (C) which does not directly support the description of generated programs. These specifications, which we'll call metadata, are not written in C, but in a meta-language. Because the the rest of the user's program typically requires a general-purpose programming system and must interact with the generated parser, the metadata is translated into C, which is then compiled and linked together with the rest of the system. The metadata thus undergoes two translation steps, and the user is always very conscious of the boundary between her metadata and the rest of her program.

- -
-
-
-

1.1. Native language metaprogramming

-
-
- -

A more interesting form of metaprogramming is available in languages such as Scheme [SS75], where the generated program specification is given in the same language as the metaprogram itself. The metaprogrammer defines her meta-language as a subset of the expressible forms of the underlying language, and program generation can take place in the same translation step used to process the rest of the user's program. This allows users to switch transparently between ordinary programming, generated program specification, and metaprogramming, often without being aware of the transition.

-
- -
-
-
-

1.2. Metaprogramming in C++

-
-
- -

In C++, it was discovered almost by accident [Unr], [Vel95a] that the template mechanism provides a rich facility for computation at compile-time. In this section, we'll explore the basic mechanisms and some common idioms used for metaprogramming in C++.

- -
-
-
-

1.2.1. Numeric computations

-
-
- -

The availability of non-type template parameters makes it possible to perform integer computations at compile-time. For example, the following template computes the factorial of its argument:

- -
-template< unsigned n >
-struct factorial
-{
-    static const unsigned value = n * factorial<n-1>::value;
-};
-
-template<>
-struct factorial<0>
-{
-    static const unsigned value = 1;
-};
-
- -

The program fragment above is called a metafunction, and it is easy to see its relationship to a function designed to be evaluated at runtime: the ‘metafunction argument’ is passed as a template parameter, and its ‘return value’ is defined as a nested static constant. Because of the hard line between the expression of compile-time and runtime computation in C++, metaprograms look different from their runtime counterparts. Thus, although as in Scheme the C++ metaprogrammer writes her code in the same language as the ordinary program, only a subset of the full C++ language is available to her: those expressions which can be evaluated at compile-time. Compare the above with a straightforward runtime definition of the factorial function:

- -
-unsigned factorial(unsigned N)
-{
-    return N == 0 ? 1 : N * factorial(N - 1);
-}
-
- -

While it is easy to see the analogy between the two recursive definitions, recursion is in general more important to C++ metaprograms than it is to runtime C++. In contrast to languages such as Lisp where recursion is idiomatic, C++ programmers will typically avoid recursion when possible. This is done not only for efficiency reasons, but also because of ‘cultural momentum’: recursive programs are simply harder (for C++ programmers) to think about. Like pure Lisp, though, the C++ template mechanism is a functional programming language: as such it rules out the use of data mutation required to maintain loop variables.

- -

A key difference between the runtime and compile-time factorial functions is the expression of the termination condition: our meta-factorial uses template specialization as a kind of pattern-matching mechanism to describe the behavior when N is zero. The syntactic analogue in the runtime world would require two separate definitions of the same function. In this case the impact of the second definition is minimal, but in large metaprograms the cost of maintaining and understanding the terminating definitions can become significant.

- -

Note also that a C++ metafunction's return value must be named. The name chosen here, value, is the same one used for all numeric returns in the MPL. As we'll see, establishing a consistent naming convention for metafunction returns is crucial to the power of the library.

-
- -
-
-
-

1.2.2. Type computations

-
-
- -

How could we apply our factorial metafunction? We might, for example, produce an array type of an appropriate size to hold all permutations of instances of another type:

- -
-// permutation_holder<T>::type is an array type which can contain 
-// all permutations of a given T.
-
-// unspecialized template for scalars
-template< typename T >
-struct permutation_holder
-{
-    typedef T type[1][1];
-};
-
-// specialization for array types
-template< typename T, unsigned N >
-struct permutation_holder<T[N]>
-{
-    typedef T type[factorial<N>::value][N];
-};
-
- -

Here we have introduced the notion of a type computation. Like factorial above, permutation_holder template is a metafunction. However, where factorial manipulates unsigned integer values, permutation_holder accepts and ‘returns’ a type (as the nested typedef type). Because the C++ type system provides a much richer set of expressions than anything we can use as a nontype template argument (e.g. the integers), C++ metaprograms tend to be composed mostly of type computations.

-
- -
-
-
-

1.2.3. Type sequences

-
-
- -

The ability to programmatically manipulate collections of types is a central tool of most interesting C++ metaprograms. Because this capability is so well-supported by the MPL, we'll provide just a brief introduction to the basics here. Later on, we'll revisit the example below to show how it can be implemented using MPL.

- -

First, we'd need a way to represent the collection. One idea might be to store the types in a structure:

- -
-struct types
-{
-    int t1;
-    long t2;
-    std::vector<double> t3;
-};
-
- -

Unfortunately, this arrangement is not susceptible to the compile-time type introspection power that C++ gives us: there's no way to find out what the names of the members are, and even if we assume that they're named according to some convention as above, there's no way to know how many members there are. The key to solving this problem is to increase the uniformity of the representation. If we have a consistent way to get the first type of any sequence and the rest of the sequence, we can easily access all members:

- -
-template< typename First, typename Rest >
-struct cons
-{
-    typedef First first;
-    typedef Rest rest;
-};
-
-struct nil {};
-
-typedef
-      cons<int
-    , cons<long
-    , cons<std::vector<double>
-    , nil
-    > > > my_types;
-
- -

The structure described by types above is the compile-time analogue of a singly-linked list; it has been first introduced by Czarnecki and Eisenecker in [CE98]. Now that we've adjusted the structure so that the C++ template machinery can ‘peel it apart’, let's examine a simple metafunction which does so. Suppose a user wished to find the largest of an arbitrary collection of types. We can apply the recursive metafunction formula which should by now be familiar:

- -
-

Example 1. 'largest' metafunction

- -
-// choose the larger of two types
-template<
-      typename T1
-    , typename T2
-    , bool choose1 = (sizeof(T1) > sizeof(T2)) // hands off!
-    >
-struct choose_larger
-{
-    typedef T1 type;
-};
-
-// specialization for the case where sizeof(T2) >= sizeof(T1)
-template< typename T1, typename T2 >
-struct choose_larger< T1,T2,false >
-{
-    typedef T2 type;
-};
-
-// get the largest of a cons-list
-template< typename T > struct largest;
-
-// specialization to peel apart the cons list
-template< typename First, typename Rest >
-struct largest< cons<First,Rest> >
-    : choose_larger< First, typename largest<Rest>::type >
-{
-    // type inherited from base
-};
-
-// specialization for loop termination
-template< typename First >
-struct largest< cons<First,nil> >
-{
-    typedef First type;
-};
-
-int main()
-{
-    // print the name of the largest of my_types
-    std::cout
-        << typeid(largest<my_types>::type).name()
-        << std::endl
-        ;
-}
-
-
- -

There are several things worth noticing about this code:

- -
-
    -
  • -

    It uses a few ad-hoc, esoteric techniques, or ‘hacks’. The default template argument choose1 (labeled ‘hands off!’) is one example. Without it, we would have needed yet another template to provide the implementation of choose_larger, or we would have had to provide the computation explicitly as a parameter to the template - perhaps not bad for this example, but it would make choose_larger much less useful and more error-prone. The other hack is the derivation of a specialization of largest from choose_larger. This is a code-saving device which allows the programmer to avoid writing ‘typedef typename ...::type type’ in the template body.

    -
  • - -
  • -

    Even this simple metaprogram uses three separate partial specializations. The largest metafunction uses two specializations. One might expect that this indicates there are two termination conditions, but there are not: one specialization is needed simply to deal with access to the sequence elements. These specializations make the code difficult to read by spreading the definition of a single metafunction over several C++ template definitions. Also, because they are partial specializations, they make the code unusable for a large community of C++ programmers whose compilers don't support that feature.

    -
  • -
-
- -

While these techniques are, of course, a valuable part of the arsenal of any good C++ metaprogrammer, their use tends to make programs written in what is already an unusual style harder-to-read and harder-to-write. By encapsulating commonly-used structures and dealing with loop terminations internally, the MPL reduces the need for both tricky hacks and for template specializations.

-
-
- -
-
-
-

1.3. Why metaprogramming?

-
-
- -

It's worth asking why anyone would want to do this. After all, even a simple toy example like the factorial metafunction is somewhat esoteric. To show how the type computation can be put to work, let's examine a simple example. The following code produces an array containing all possible permutations of another array:

- -
-// can't return an array in C++, so we need this wrapper
-template< typename T >
-struct wrapper
-{
-    T x;
-};
-
-// return an array of the N! permutations of 'in'
-template< typename T >
-wrapper< typename permutation_holder<T>::type >
-all_permutations(T const& in)
-{
-    wrapper<typename permutation_holder<T>::type> result;
-
-    // copy the unpermutated array to the first result element
-    unsigned const N = sizeof(T) / sizeof(**result.x);
-    std::copy(&*in, &*in + N, result.x[0]);
-
-    // enumerate the permutations
-    unsigned const result_size = sizeof(result.x) / sizeof(T);
-    for (T* dst = result.x + 1; dst != result.x + result_size; ++dst)
-    {
-        T* src = dst - 1;
-        std::copy(*src, *src + N, *dst);
-        std::next_permutation(*dst, *dst + N);
-    }
-    return result;
-}
-
- -

The runtime definition of factorial would be useless in all_permutations above, since in C++ the sizes of array members must be computed at compile-time. However, there are alternative approaches; how could we avoid metaprogramming, and what would the consequences be?

- -
-
    -
  1. -

    We could write programs to interpret the metadata directly. In our factorial example, the array size could have been a runtime quantity; then we'd have been able to use the straightforward factorial function. However, that would imply the use of dynamic allocation, which is often expensive.

    - -

    To carry this further, YACC might be rewritten to accept a pointer-to-function returning tokens from the stream to be parsed, and a string containing the grammar description. This approach, however, would impose unacceptable runtime costs for most applications: either the parser would have to treat the grammar nondeterministically, exploring the grammar for each parse, or it would have to begin by replicating at runtime the substantial table-generation and optimization work of the existing YACC for each input grammar.

    -
  2. - -
  3. -

    We could replace the compile-time computation with our own analysis. After all, the size of arrays passed to all_permutations are always known at compile-time, and thus can be known to its user. We could ask the user to supply the result type explicitly:

    - -
    -template< typename Result, typename T >
    -Result all_permutations(T const& input);
    -
    - -

    The costs to this approach are obvious: we give up expressivity (by requiring the user to explicitly specify implementation details), and correctness (by allowing the user to specify them incorrectly). Anyone who has had to write parser tables by hand will tell you that the impracticality of this approach is the very reason of YACC's existence.

    - -

    In a language such as C++, where the metadata can be expressed in the same language as the rest of the user's program, expressivity is further enhanced: the user can invoke metaprograms directly, without learning a foreign syntax or interrupting the flow of her code.

    -
  4. -
-
- -

So, the motivation for metaprogramming comes down to the combination of three factors: efficiency, expressivity, and correctness. While in classical programming there is always a tension between expressivity and correctness on one hand and efficiency on the other, in the metaprogramming world we wield new power: we can move the computation required for expressivity from runtime to compile-time.

-
- -
-
-
-

1.4. Why a metaprogramming library?

-
-
- -

One might just as well ask why we need any generic library:

- -
-
    -
  • -

    Quality. Code that is appropriate for a general-purpose library is usually incidental to the purpose of its users. To a library developer, it is the central mission. On average, the containers and algorithms provided by any given C++ standard library implementation are more-flexible and better-implemented than the project-specific implementations which abound, because library development was treated as an end in itself rather than a task incidental to the development of some other application. With a centralized implementation for any given function, optimizations and improvements are more likely to have been applied.

    -
  • - -
  • -

    Re-use. More important even than the re-use of code which all libraries provide, a well-designed generic library establishes a framework of concepts and idioms which establishes a reusable mental model for approaching problems. Just as the C++ Standard Template Library gave us iterator concepts and a function object protocol, the Boost Metaprogramming Library provides type-iterators and metafunction class protocol. A well-considered framework of idioms saves the metaprogrammer from considering irrelevant implementation details and allows her to concentrate on the problem at hand.

    -
  • - -
  • -

    Portability. A good library can smooth over the ugly realities of platform differences. While in theory a metaprogramming library is fully generic and shouldn't be concerned with these issues, in practice support for templates remains inconsistent even four years after standardization. This should perhaps not be surprising: C++ templates are the language's furthest-reaching and most complicated feature, which largely accounts for the power of metaprogramming in C++.

    -
  • - -
  • -

    Fun. Repeating the same idioms over and over is tedious. It makes programmers tired and reduces productivity. Furthermore, when programmers get bored they get sloppy, and buggy code is even more costly than slowly-written code. Often the most useful libraries are simply patterns that have been “plucked” by an astute programmer from a sea of repetition. The MPL helps to reduce boredom by eliminating the need for the most commonly-repeated boilerplate coding patterns.

    -
  • -
-
- -

As one can see, the MPL's development is motivated primarily by the same practical, real-world considerations that justify the development of any other library. Perhaps this is an indication that template metaprogramming is finally ready to leave the realm of the esoteric and enter the lingua franca of every day programmers.

-
-
- - - - - diff --git a/doc/paper/html/lambda.html b/doc/paper/html/lambda.html deleted file mode 100644 index 7e5bbc2..0000000 --- a/doc/paper/html/lambda.html +++ /dev/null @@ -1,165 +0,0 @@ - - - - -3. Lambda facility - - - - - - - - - - - -
-
-
-

3. Lambda facility

-
-
- -

The MPL's lambda facility allows the inline composition of class templates into ‘lambda expressions’, which are classes and can therefore be passed around as ordinary metafunction classes, or transformed into metafunction classes before application using the expression:

- -
-typedef mpl::lambda<expr>::type func;
-
- -

For example, boost::remove_const traits template from Boost type_traits library [TTL] is a class template (obviously), or a metafunction in MPL terminology. The simplest example of an ‘inline composition’ of it would be something like:

- -
-typedef boost::remove_const<_1> expr;
-
- -

This forms a so called ‘lambda expression’, which is neither a metafunction class, nor a metafunction, yet can be passed around everywhere because it's an ordinary C++ class, because all MPL facilities are polymorphic with respect to their arguments. Now, that lambda expression can be transformed into a metafunction class using the MPL's lambda facility:

- -
-typedef boost::remove_const<_1> expr;
-typedef mpl::lambda<expr>::type func;
-
- -

The func is a unary metafunction class and can be used as such. In particular, it can be pass around or invoked (applied):

- -
-typedef mpl::apply<func,int const>::type res;
-BOOST_MPL_ASSERT_IS_SAME(res, int);
-
- -

or even

- -
-typedef func::apply<int const>::type res;
-BOOST_MPL_ASSERT_IS_SAME(res, int);
-
- -

Inline composition is very appealing syntactically when one deals with metafunctions, because it makes the expression obvious:

- -
-typedef mpl::logical_or<
-      mpl::less< mpl::size_of<_1>, mpl::int_c<16> >
-    , boost::is_same<_1,_2>
-    > expr;
-
-typedef mpl::lambda<expr>::type func;
-
- -

And one does not have to specify the last part (typedef lambda<expr>::type func), because all the algorithms do this to any of their metafunction class operands internally (a lambda<T>::type expression applied to a metafunction class gives back the same metafunction class, so it's safe to apply the expression unconditionally).

- -

The alternative way to write an equivalent of the above metafunction class would be:

- -
-typedef bind<
-      mpl::meta_fun2<mpl::logical_or>
-    , mpl::bind< mpl::meta_fun2<mpl::less>
-        , mpl::bind< mpl::meta_fun1<mpl::size_of>,_1 >
-        , mpl::int_c<16>
-        >
-    , mpl::bind< mpl::meta_fun2<boost::is_same>,_1,_2 >
-    > func;
-
- -

Or to use mpl::compose_ family of templates in a similar way. Here, we use mpl::meta_fun templates to convert metafunctions into metafunction classes and then combine them using mpl::bind. The transformation from this form to the above inline lambda expression and vice-versa is mechanical, and that is essentially what the typedef mpl::lambda<expr>::type expression does.

- -

For its own metafunctions (algorithms, primitives, etc.), MPL enables one to write the above in a less cumbersome way:

- -
-typedef mpl::bind<
-      mpl::logical_or<>
-    , mpl::bind< mpl::less<>, mpl::bind<mpl::size_of<>,_1>, mpl::int_c<16> >
-    , mpl::bind< mpl::make_f2<boost::is_same>, _1,_2 >
-    > func;
-
- -

Note that we still have to wrap is_same into make_f2, because it's a foreign template.

- -

Now, about combining class template metafunctions and metafunction classes in the single lambda expression - it can be done like this:

- -
-struct my_predicate
-{
-    template< typename T1, typename T2 > struct apply
-    {
-        //...
-    };
-};
-
-typedef mpl::logical_or<
-      mpl::less< mpl::size_of<_>,mpl::int_c<16> >
-    , mpl::bind< my_predicate,_,_ > // here
-    > expr;
-
- -

To bind something to one of its arguments (or change the order of parameters), then use either:

- -
-typedef mpl::logical_or<
-      mpl::less< mpl::size_of<_>,mpl::int_c<16> >
-    , mpl::bind<my_predicate,int,_>::type // here
-    > expr;
-
- -

or

- -
-typedef mpl::logical_or<
-      mpl::less< mpl::size_of<_>,mpl::int_c<16> >
-    , my_predicate::apply<int,_> // here
-    > expr;
-
-
- - - - - diff --git a/doc/paper/html/refs.html b/doc/paper/html/refs.html deleted file mode 100644 index ae8564f..0000000 --- a/doc/paper/html/refs.html +++ /dev/null @@ -1,152 +0,0 @@ - - - - -References - - - - - - - - - - -
-
-
-

References

-
-
- -
-

[Abr01] David Abrahams and Carlos Pinto Coelho, Effects of Metaprogramming Style on Compilation Time, 2001

-
- -
-

[Ale01] Andrei Alexandrescu, Modern C++ Design: Generic Programming and Design Patterns Applied, Addison-Wesley, ISBN 0-201-70431-5, 2001

-
- -
-

[CE98] Krzysztof Czarnecki and Ulrich Eisenecker, Metalisp, http://home.t-online.de/home/Ulrich.Eisenecker/meta.htm

-
- -
-

[CE00] Krzysztof Czarnecki and Ulrich Eisenecker, Generative Programming: Methods, Tools, and Applications, Addison-Wesley, ISBN 0-201-30977-7, 2000

-
- -
-

[EBNF] ISO/IEC 14977:1996(E), Information technology — Syntactic metalanguage — Extended BNF, ISO/IEC, 1996

-
- -
-

[GHJ+95] Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides, Design Patterns, Elements of Reusable Object-Oriented Software, Addison-Wesley, ISBN 0-201-63361-2, 1995

-
- -
-

[HU79] Hopcroft and Ullman, Introduction to automata theory, languages and computations, Addison-Wesley, 1979

-
- -
-

[Hud89] Paul Hudak, Conception, Evolution, and Application of Functional Programming Languages, ACM Computing Surveys, Association for Computing Machinery (ACM), ISSN 0360-0300, Vol. 21, No. 3, pp. 359-411, September, 1989

-
- -
-

[Hun91] Immo Huneke, Finite State Machines: A Model of Behavior for C++, C++ Report, SIGS Publications Inc., ISSN 1040-6042, 1991

-
- -
-

[ISO98] ISO/IEC 14882:1998(E), Programming languages — C++, ISO/IEC, 1998

-
- -
-

[Joh79] Stephen C. Johnson, Yacc: Yet Another Compiler Compiler, UNIX Programmer's Manual, Vol. 2b, pp. 353-387, 1979

-
- -
-

[Laf00] David Lafreniere, State Machine Design in C++, C/C++ User Journal, CMP Media LCC, ISSN 1075-2838, Vol. 18, No. 5, May 1998

-
- -
-

[Loki] The Loki library, http://sourceforge.net/projects/loki-lib/

-
- -
-

[Mar98] Robert C. Martin, UML Tutorial: Finite State Machines, C++ Report, SIGS Publications Inc., ISSN 1040-6042, June 1998

-
- -
-

[MPLR] Boost MPL Library Reference Documentation, http://www.mywikinet.com/mpl/ref/Table_of_Content.html

-
- -
-

[PRE] Vesa Karvonen, Boost Preprocessor Metaprogramming library, http://www.boost.org/libs/preprocessor/doc/

-
- -
-

[SMC] Robert C. Martin, SMC - Finite State Machine Compiler (C++), http://www.objectmentor.com/resources/downloads/index

-
- -
-

[STL94] A. A. Stepanov and M. Lee, The Standard Template Library, Hewlett-Packard Laboratories, 1994

-
- -
-

[SPL] Boost Smart Pointer library, http://www.boost.org/libs/smart_ptr/

-
- -
-

[SS75] Gerald J. Sussman and Guy L. Steele Jr., Scheme: An interpreter for extended lambda calculus, MIT AI Memo 349, Massachusetts Institute of Technology, May 1975

-
- -
-

[TTL] Boost Type Traits library, http://www.boost.org/libs/type_traits/

-
- -
-

[Vel95a] Todd Veldhuizen, Using C++ template metaprograms, C++ Report, SIGS Publications Inc., ISSN 1040-6042, Vol. 7, No. 4, pp. 36-43, May 1995

-
- -
-

[Vel95b] Todd Veldhuizen, Expression templates, C++ Report, SIGS Publications Inc., ISSN 1040-6042, Vol. 7, No. 5, pp. 26-31, Jun 1995

-
- -
-

[Unr] Erwin Unruh, Prime number computation, ANSI X3J16-94-0075/ISO WG21-462

-
-
- - - - - diff --git a/doc/paper/html/usage.html b/doc/paper/html/usage.html deleted file mode 100644 index 6eede7b..0000000 --- a/doc/paper/html/usage.html +++ /dev/null @@ -1,920 +0,0 @@ - - - - -2. Basic usage - - - - - - - - - - - -
-
-
-

2. Basic usage

-
-
- -
-
-
-

2.1. Conditional type selection

-
-
- -

Conditional type selection is the simplest basic construct of C++ template metaprogramming. Veldhuizen [Vel95a] was the first to show how to implement it, and Czarnecki and Eisenecker [CE00] first presented it as a standalone library primitive. The MPL defines the corresponding facility as follows:

- -
-template<
-      typename Condition
-    , typename T1
-    , typename T2
-    >
-struct if_
-{
-    typedef /*unspecified*/ type;
-};
-
- -

Note that the first template parameter of the template is a type.

- -
-// usage/semantics
-typedef mpl::if_<mpl::true_c,char,long>::type t1;
-typedef mpl::if_<mpl::false_c,char,long>::type t2;
-
-BOOST_MPL_ASSERT_IS_SAME(t1, char);
-BOOST_MPL_ASSERT_IS_SAME(t2, long);
-
- -

The construct is important because template metaprograms often contain a lot of decision-making code, and, as we will show, spelling it manually every time via (partial) class template specialization quickly becomes impractical. The template is also important from the point of encapsulating the compiler workarounds.

- -
-
-
-

2.1.1. Delayed evaluation

-
-
- -

The way the C++ template instantiation mechanism works imposes some subtle limitations on applicability of the type selection primitive (if_), compared to a manually implemented equivalent of the selection code. For example, suppose we are implementing a pointed_type traits template such that pointed_type<T>::type instantiated for a T that is either a plain pointer (U*), std::auto_ptr<U>, or any of the Boost smart pointers [SPL], e.g. boost::scoped_ptr<U>, will give us the pointed type (U):

- -
-BOOST_MPL_ASSERT_IS_SAME(pointed_type<my*>::type, my);
-BOOST_MPL_ASSERT_IS_SAME(pointed_type< std::auto_ptr<my> >::type, my);
-BOOST_MPL_ASSERT_IS_SAME(pointed_type< boost::scoped_ptr<my> >::type, my);
-
- -

Unfortunately, the straightforward application of if_ to this problem does not work: 1

- -
-template< typename T >
-struct pointed_type
-    : mpl::if_<
-          boost::is_pointer<T>
-        , typename boost::remove_pointer<T>::type
-        , typename T::element_type // #1
-        >
-{
-};
-
-// the following code causes compilation error in line #1:
-// name followed by "::" must be a class or namespace name
-typedef pointed_type<char*>::type result;
-
- -

Clearly, the expression typename T::element_type is not valid in the case of T == char*, and that's what the compiler is complaining about. Implementing the selection code manually solves the problem:

- -
-namespace aux {
-// general case
-template< typename T, bool is_pointer = false >
-struct select_pointed_type
-{
-    typedef typename T::element_type type;
-};
-
-// specialization for plain pointers
-template< typename  T >
-struct select_pointed_type<T,true>
-{
-    typedef typename boost::remove_pointer<T>::type type;
-};
-}
-
-template< typename T >
-struct pointed_type
-   : aux::select_pointed_type<
-          T, boost::is_pointer<T>::value
-        >
-{
-};
-
- -

But this quickly becomes awkward if needs to be done repeatedly, and this awkwardness is compounded when partial specialization is not available. We can try to work around the problem as follows:

- -
-namespace aux {
-template< typename T >
-struct element_type
-{
-     typedef typename T::element_type type;
-};
-}
-
-template< typename T >
-struct pointed_type
-{
-    typedef typename mpl::if_<
-          boost::is_pointer<T>
-        , typename boost::remove_pointer<T>::type
-        , typename aux::element_type<T>::type
-        >::type type;
-};
-
- -

but this doesn't work either - the access to the aux::element_type<T>'s nested type member still forces the compiler to instantiate element_type<T> with T == char*, and that instantiation is, of course, invalid. Also, although in our case this does not lead to a compile error, the boost::remove_pointer<T> template always gets instantiated as well, and for the same reason (because we are accessing its nested type member). Unnecessary instantiation that is not fatal may or may be not a problem, depending on the ‘weight’ of the template (how much the instantiation taxes the compiler), but a general rule of thumb would be to avoid such code.

- -

Returning to our error, to make the above code compile, we need to factor the act of ‘asking’ aux::element_type<T> for its nested type out of the if_ invocation. The fact that both the boost::remove_pointer<T> trait template and aux::element_type<T> use the same naming convention for their result types makes the refactoring easier:

- -
-template< typename T >
-struct pointed_type
-{
- private:
-    typedef typename mpl::if_<
-          boost::is_pointer<T>
-        , boost::remove_pointer<T>
-        , aux::element_type<T>
-        >::type func_;
-
- public:
-    typedef typename func_::type type;
-};
-
- -

Now the compiler is guaranteed not to instantiate both boost::remove_pointer<T> and aux::element_type<T>, even although they are used as actual parameters to the if_ template, so we are allowed to get away with aux::element_type<char*> so long as it won't end up being selected as func_.

- -

The above technique is so common in template metaprograms, that it even makes sense to facilitate the selection of a nested type member by introducing a high-level equivalent to if_ - the one that will do the func_::type operation (that is called [nullary] metafunction class application) as a part of its invocation. The MPL provides such template - it's called apply_if. Using it, we can re-write the above code as simple as:

- -
-template< typename T >
-struct pointed_type
-{
-    typedef typename mpl::apply_if<
-          boost::is_pointer<T>
-        , boost::remove_pointer<T>
-        , aux::element_type<T>
-        >::type type;
-};
-
- -

To make our techniques review complete, let's consider a slightly different example - suppose we want to define a high-level wrapper around boost::remove_pointer traits template [TTL], which will strip the pointer qualification conditionally. We will call it remove_pointer_if:

- -
-template<
-      typename Condition
-    , typename T
-    >
-struct remove_pointer_if
-{
-    typedef typename mpl::if_<
-          Condition
-        , typename boost::remove_pointer<T>::type
-        , T
-        >::type type;
-};
-
- -

Now the above works the first time, but it suffers from the problem we mentioned earlier - boost::remove_pointer<T> gets instantiated even if its result is never used. In the metaprogramming world compilation time is an important resource [Abr01], and it is wasted by unnecessary template instantiations. We've just seen how to deal with the problem when both arguments to if_ are the results of nullary metafunction class applications, but in this example one of the arguments (T) is just a simple type, so the refactoring just doesn't seem possible.

- -

The easiest way out of this situation would be to pass to if_ a real nullary metafunction instead of T - the one that returns T on its invocation. The MPL provides a simple way to do it - we just substitute identity<T> and apply_if for T and if_:

- -
-template<
-      typename Condition
-    , typename T
-    >
-struct remove_pointer_if
-{
-    typedef typename mpl::apply_if<
-          Condition
-        , boost::remove_pointer<T>
-        , mpl::identity<T>
-        >::type type;
-};
-
- -

which gives us exactly what we wanted.

-
-
- -
-
-
-

2.2. Metafunctions

-
-
- -
-
-
-

2.2.1. The simple form

-
-
- -

In C++, the basic underlying language construct which allows parameterized compile-time computation is the class template ([ISO98], section 14.5.1 [temp.class]). A bare class template is the simplest possible model we could choose for metafunctions: it can take types and/or non-type arguments as actual template parameters, and instantiation ‘returns’ a new type. For example, the following produces a type derived from its arguments:

- -
-template< typename T1, typename T2 >
-struct derive : T1, T2
-{
-};
-
- -

However, this model is far too limiting: it restricts the metafunction result not only to class types, but to instantiations of a given class template, to say nothing of the fact that every metafunction invocation introduces an additional level of template nesting. While that might be acceptable for this particular metafunction, any model which prevented us from ‘returning’, say, int is obviously not general enough. To meet this basic requirement, we must rely on a nested type to provide our return value:

- -
-template< typename T1, typename T2 >
-struct derive
-{
-    struct type : N1, N2 {};
-};
-
-// silly specialization, but demonstrates "returning" int
-template<>
-struct derive<void,void>
-{
-    typedef int type;
-};
-
- -

Veldhuizen [Vel95a] was first to talk about class templates of this form as ‘compile-time functions’, and Czarnecki and Eisenecker [CE00] have introduced ‘template metafunction’ as an equivalent term (they also use the simpler term ‘metafunction’, as do we). Czarnecki and Eisenecker have also recognized the limitations of the simple metafunction representation and suggested the form that we discuss in Section 2.2.3.

-
- -
-
-
-

2.2.2. Higher-order metafunctions

-
-
- -

While syntactically simple, the simple template metafunction form does not always interact optimally with the rest of C++. In particular, the simple metafunction form makes it unnecessarily awkward and tedious to define and work with higher-order metafunctions (metafunctions that operate on other metafunctions). In order to pass a simple metafunction to another template, we need to use template template parameters:

- -
-// returns F(T1,F(T2,T3))
-template<
-      template<typename> class F
-    , typename T1
-    , typename T2
-    , typename T3
-    >
-struct apply_twice
-{
-  typedef typename F<
-        T1
-      , typename F<T2,T3>::type
-      >::type type;
-};
-
-// a new metafunction returning a type derived from T1, T2, and T3
-template<
-      typename T1
-    , typename T2
-    , typename T3
-    >
-struct derive3
-    : apply_twice<derive,T1,T2,T3>
-{
-};
-
- -

This looks different, but it seems to work. 2 However, things begin to break down noticeably when we want to ‘return’ a metafunction from our metafunction:

- -
-// returns G s.t. G(T1,T2,T3) == F(T1,F(T2,T3))
-template< template<typename> class F >
-struct compose_self
-{
-    template<
-          typename T1
-        , typename T2
-        , typename T3
-        > 
-    struct type
-        : apply_twice<F,T1,T2,T3>
-    {
-    };
-};
-
- -

The first and most obvious problem is that the result of applying compose_self is not itself a type, but a template, so it can't be passed in the usual ways to other metafunctions. A more subtle issue, however, is that the metafunction ‘returned’ is not exactly what we intended. Although it acts just like apply_twice, it differs in one important respect: its identity. In the C++ type system, compose_self<F>::template type<T,U,V> is not a synonym for apply_twice<F,T,U,V>, and any metaprogram which compared metafunctions would discover that fact.

- -

Because C++ makes a strict distinction between type and class template template parameters, reliance on simple metafunctions creates a ‘wall’ between metafunctions and metadata, relegating metafunctions to the status of second-class citizens. For example, recalling our introduction to type sequences, there's no way to make a cons list of metafunctions:

- -
-typedef cons<derive, cons<derive3, nil> > derive_functions; // error!
-
- -

We might consider redefining our cons cell so we can pass derive as the head element:

- -
-template <
-      template< template<typename T, typename U> class F
-    , typename Tail
-    >
-struct cons;
-
- -

However, now we have another problem: C++ templates are polymorphic with respect to their type arguments, but not with respect to template template parameters. The arity (number of parameters) of any template template parameter is strictly enforced, so we still can't embed derive3 in a cons list. Moreover, polymorphism between types and metafunctions is not supported (the compiler expects one or the other), and as we've seen, the syntax and semantics of ‘returned’ metafunctions is different from that of returned types. Trying to accomplish everything with the simple template metafunction form would seriously limit the applicability of higher-order metafunctions and would have an overall negative effect on the both conceptual and implementation clarity, simplicity and size of the library.

-
- -
-
-
-

2.2.3. Metafunction classes

-
-
- -

Fortunately, the truism that ‘there is no problem in software which can't be solved by adding yet another level of indirection’ applies here. To elevate metafunctions to the status of first-class objects, the MPL introduces the concept of a ‘metafunction class’:

- -
-// metafunction class form of derive
-struct derive
-{
-    template< typename N1, typename N2 >
-    struct apply
-    {
-        struct type : N1, N2 {};
-    };
-};
-
- -

This form should look familiar to anyone acquainted with function objects in STL, with the nested apply template taking the same role as the runtime function-call operator. In fact, compile-time metafunction classes have the same relationship to metafunctions that runtime function objects have to functions:

- -
-// function form of add
-template< typename T > T add(T x, T y) { return x + y; }
-
-// function object form of add
-struct add
-{
-    template< typename T >
-    T operator()(T x, T y) { return x + y; }
-};
-
-
- -
-
-
-

2.2.4. One size fits all?

-
-
- -

The metafunction class form solves all the problems with ordinary template metafunction mentioned earlier: since it is a regular class, it can be placed in compile-time metadata sequences and manipulated by other metafunctions using the same protocols as for any other metadata. We thereby avoid the code-duplication needed to provide versions of each library component to operate on ordinary metadata and on metafunctions with each distinct supported arity.

- -

On the other hand, it seems that accepting metafunction classes as the representation for compile-time function entities imposes code duplication danger as well: if the library's own primitives, algorithms, etc. are represented as class templates, that means that one either cannot reuse these algorithms in the context of higher-order functions, or she have to duplicate all algorithms in the second form, so, for instance, there would be two versions of find:

- -
-// user-friendly form
-template<
-      typename Sequence
-    , typename T
-    >
-struct find
-{
-    typedef /* ... */ type;
-};
-
-// "metafunction class" form
-struct find_func
-{
-    template< typename Sequence, typename T >
-    struct apply
-    {
-        typedef /* ... */ type;
-    };
-};
-
- -

Of course, the third option is to eliminate ‘user-friendly form’ completely so one would always have to write:

- -
-typedef mpl::find::apply<list,long>::type iter;
-// or, if one prefers,
-// typedef mpl::apply< mpl::find,list,long >::type iter;
-
- -

instead of

- -
-typedef mpl::find<list,long>::type iter;
-
- -

That too would hurt usability, considering that the direct invocations of library's algorithms are far more often-used than passing algorithms as arguments to other algorithms/metafunctions.

-
- -
-
-
-

2.2.5. From metafunction to metafunction class

-
-
- -

The MPL's answer to this dilemma is lambda expressions. Lambda is the mechanism that enables the library to curry metafunctions and convert them into metafunction classes, so when one wants to pass the find algorithm as an argument to a higher-order metafunction, she just write:

- -
-using namespace mpl::placeholder;
-typedef mpl::apply< my_f, mpl::find<_1,_2> >::type result;
-
- -

where _1 and _2 are placeholders for the first and second arguments to the resulting metafunction class. This preserves the intuitive syntax below for when the user wants to use find directly in her code:

- -
-typedef mpl::find<list,long>::type iter;
-
- -

Lambda facility is described in more details in Section 3.

-
-
- -
-
-
-

2.3. Sequences, algorithms, and iterators

-
-
- -
-
-
-

2.3.1. Introduction

-
-
- -

Compile-time iteration over a sequence (of types) is one of the basic concepts of template metaprogramming. Differences in types of objects being manipulated is the most common point of variability of similar but not identical code/design, and such designs are the direct target for some metaprogramming. Templates were originally designed to solve this exact problem (e.g. std::vector). However, without predefined abstractions/constructs for manipulating/iterating over sequences of types (as opposed to standalone types), and without known techniques for emulating these constructs using the current language facilities, their effect on helping high-level metaprogramming happen has been limited.

- -

Czarnecki and Eisenecker [CE98], [CE00] were the first to introduce compile-time sequences of types and some simple algorithms on them, although the idea of representing common data structures like trees, lists, etc. at compile time, using class template composition has been around for a while (e.g. most of the expression template libraries build such trees as a part of their expression "parsing" process [Vel95b]). Alexandrescu [Ale01] used lists of types and some algorithms on them to implement several design patterns; the accompanying code is known as the Loki library [Loki].

-
- -
-
-
-

2.3.2. Algorithms and sequences

-
-
- -

Most of the algorithms in the Boost Metaprogramming Library operate on sequences. For example, searching for a type in a list looks like this:

- -
-typedef mpl::list<char,short,int,long,float,double> types;
-typedef mpl::find<types,long>::type iter;
-
- -

Here, find accepts two parameters - a sequence to search (types) and the type to search for (long) - and returns an iterator iter pointing to the first element of the sequence such that iter::type is identical to long. If no such element exists, iter is identical to end<types>::type. Basically, this is how one would search for a value in a std::list or std::vector, except that mpl::find accepts the sequence as a single parameter, while std::find takes two iterators. Everything else is pretty much the same - the names are the same, the semantics are very close, there are iterators, and one can search not only by type, but also by using a predicate:

- -
-typedef mpl::find_if< types,boost::is_float<_> >::type iter;
-
- -

This conceptual/syntactical similarity with the STL is not coincidental. Reusing the conceptual framework of the STL in the compile-time world allows us to apply familiar and sound approaches for dealing with sequential data structures. The algorithms and idioms which programmers already know from the STL can be applied again at compile-time. We consider this to be one of MPL's greatest strengths, distinguishing it from earlier attempts to build a template metaprogramming library.

-
- -
-
-
-

2.3.3. Sequence concepts

-
-
- -

In the find example above, we searched for the type in a sequence built using the mpl::list template; but list is not the only sequence that the library provides. Neither is mpl::find or any other algorithm hard-coded to work only with list sequences. list is just one model of MPL's Forward Sequence concept, and find works with anything that satisfies this concept's requirements. The hierarchy of sequence concepts in MPL is quite simple - a Sequence is any compile-time entity for which begin<> and end<> produce iterators to the range of its elements; a Forward Sequence is a Sequence whose iterators satisfy Forward Iterator requirements; a Bidirectional Sequence is a Forward Sequence whose iterators satisfy Bidirectional Iterator requirements; finally, a Random Access Sequence is a Bidirectional Sequence whose iterators satisfy Random Access Iterator requirements. 3

- -

Decoupling algorithms from particular sequence implementations (through iterators) allows a metaprogrammer to create her own sequence types and to retain the rest of the library at her disposal. For example, one can define a tiny_list for dealing with sequences of three types as follows:

- -
-template< typename TinyList, long Pos >
-struct tiny_list_item;
-
-template< typename TinyList, long Pos >
-struct tiny_list_iterator
-{
-    typedef typename tiny_list_item<TinyList,Pos>::type type;
-    typedef tiny_list_iterator<TinyList, Pos-1> prior;
-    typedef tiny_list_iterator<TinyList, Pos+1> next;
-};
-
-template< typename T0, typename T1, typename T2 >
-struct tiny_list
-{
-    typedef tiny_list_iterator<tiny_list, 0> begin;
-    typedef tiny_list_iterator<tiny_list, 3> end;
-    typedef T0 type0;
-    typedef T1 type1;
-    typedef T2 type2;
-};
-
-template< typename TinyList >
-struct tiny_list_item<TinyList,0>
-{
-    typedef typename TinyList::type0 type;
-};
-
-template< typename TinyList >
-struct tiny_list_item<TinyList,1>
-{
-    typedef typename TinyList::type1 type;
-};
-
-template< typename TinyList >
-struct tiny_list_item<TinyList,2>
-{
-    typedef typename TinyList::type2 type;
-};
-
- -

and then use it with any of the library algorithms as if it were mpl::list:

- -
-typedef tiny_list< char,short,int > types;
-typedef mpl::transform<
-      types
-    , boost::add_pointer<_1>
-    >::type pointers;
-
- -

Note that tiny_list is a model of Bidirectional Sequence; it would be a Random Access Sequence if we added advance and distance members to tiny_list_iterator:

- -
-template< typename TinyList, long Pos >
-struct tiny_list_iterator
-{
-    static long const position = Pos;
-
-    typedef typename tiny_list_item<TinyList,Pos>::type type;
-    typedef tiny_list_iterator<TinyList, Pos-1> prior;
-    typedef tiny_list_iterator<TinyList, Pos+1> next;
-
-    template< typename N > struct advance
-    {
-        typedef tiny_list_iterator<
-              TinyList
-            , Pos + N::value
-            > type;
-    };
-
-    template< typename Other > struct distance
-    {
-        typedef mpl::integral_c<
-              long
-            , Other::position - position
-            > type;
-    };
-};
-
- -

While the tiny_list itself might be not that interesting (after all, it can hold only three elements), if the technique above could be automated so we would be able to define not-so-tiny sequences (with five, ten, twenty, etc. elements), it would be very valuable. 4

- -

External code generation is an option, but there exists a solution within the language. However, it is not a template metaprogramming, but rather preprocessor metaprogramming. In fact, MPL's vector - a fixed-size type sequence that provides random-access iterators - is implemented very much like the above tiny_list - using the Boost Preprocessor library [PRE].

-
- -
-
-
-

2.3.4. Ad hoc example revisited

-
-
- -

So, the library provides its users with almost complete compile-time equivalent of the STL framework. Does it help them to solve their metaprogramming tasks? Let's return to our earlier largest example to see if we can rewrite it in a better way with what MPL has to offer. Well, actually, there is not much to look at, because the MPL implementation is a one-liner (we'll spread it out here for readability) 5 :

- -
-template< typename Sequence >
-struct largest
-{
-    typedef typename mpl::max_element<
-          Sequence
-          mpl::less<
-              mpl::size_of<_1>
-            , mpl::size_of<_2>
-            >
-        >::type iter;
-
-    typedef typename iter::type type;
-};
-
- -

There are no more termination conditions with tricky pattern matching, no more partial specializations; and even more importantly, it's obvious what the above code does - even although it's all templates - something that one could not say about the original version.

-
- -
-
-
-

2.3.5. iter_fold as the main iteration algorithm

-
-
- -

For the purpose of examining a little bit more of the library's internal structure, let's look at how max_element from the above example is implemented. One might expect that now we will again see all these awkward partial specializations, esoteric pattern matching, etc. Well, let's see:

- -
-template<
-      typename Sequence
-    , typename Predicate
-    >
-struct max_element
-{
-    typedef typename mpl::iter_fold<    
-          Sequence
-        , typename mpl::begin<Sequence>::type
-        , if_< less< deref<_1>,deref<_2> >, _2, _1 >
-        >::type type;
-};
-
- -

The first thing to notice here is that this algorithm is implemented in terms of another one: iter_fold. In fact, this is probably the most important point of the example, because nearly all other generic sequence algorithms in the library are implemented in terms of iter_fold. If a user should ever need to implement her own sequence algorithm, she'll almost certainly be able to do so using this primitive, which means she won't have to resort to implementing hand-crafted iteration, pattern matching of special cases for loop termination, or workarounds for lack of partial specialization. It also means that her algorithm will automatically benefit from any optimizations the library has implemented, (e.g. recursion unrolling), and that it will work with any sequence that is a model of ForwardSequence, because iter_fold does not require anything more of its sequence argument.

- -

iter_fold algorithm is basically a compile-time equivalent of the fold or reduce functions that comprise the basic and well-known primitives of many functional programming languages. An analogy more familiar to a C++ programmer would be the std::accumulate algorithm from the C++ standard library ([ISO98], section 26.4.1 [lib.accumulate]). However, iter_fold is designed to take advantage of the natural characteristics of recursive traversal: it accepts two metafunction class arguments, the first of which is applied to the state "on the way in" and the second of which is applied "on the way out".

- -

The interface to iter_fold is defined in MPL as follows:

- -
-template<
-      typename Sequence
-    , typename InitialState
-    , typename ForwardOp
-    , typename BackwardOp = _1
-    >
-struct iter_fold
-{
-    typedef /*unspecified*/ type;
-};
-
- -

The algorithm ‘returns’ the result of two-way successive applications of binary ForwardOp and BackwardOp operations to iterators in range [begin<Sequence>::type, end<Sequence>::type) and previous result of an operation; the InitialState is logically placed before the sequence and included in the forward traversal. The result type is identical to InitialState if the sequence is empty.

- -

The library also provides iter_fold_backward, fold, and fold_backward algorithms which wrap iter_fold to accommodate its most common usage patterns.

-
- -
-
-
-

2.3.6. Sequences of numbers

-
-
- -

What we've seen so far were sequences (and algorithms on sequences) of types. It is both possible and easy to manipulate compile-time values using the library as well. The only thing to remember is that in C++, class template non-type template parameters give us one more example of non-polymorphic behavior. In other words, if one declared a metafunction to take a non-type template parameter (e.g. long) it's not possible to pass anything besides compile-time integral constants to it:

- -
-template< long N1, long N2 >
-struct equal_to
-{
-    static bool const value = (N1 == N2);
-};
-
-equal_to<5,5>::value; // ok
-equal_to<int,int>::value; // error!
-
- -

And of course this doesn't work the other way around either:

- -
-typedef mpl::list<1,2,3,4,5> numbers; // error!
-
- -

While this may be an obvious limitation, it imposes yet another dilemma on the library design: on the one hand, we don't want to restrict users to type manipulations only, and on the other hand, full support for integral manipulations would require at least duplication of most of the library facilities 6 - the same situation as we would have if we had chosen to represent metafunctions as ordinary class templates. The solution for this issue is the same as well: we represent integral values by wrapping them in types 7 . For example, to create a list of numbers one can write:

- -
-typedef mpl::list<
-      mpl::int_c<1>
-    , mpl::int_c<2>
-    , mpl::int_c<3>
-    , mpl::int_c<4>
-    , mpl::int_c<5>
-    > numbers;
-
- -

Wrapping integral constants into types to make them first-class citizens is important well inside metaprograms, where one often doesn't know (and doesn't care) if the metafunctions she is using operate on types, integral values, other metafunctions, or something else, like fixed-point or rational numbers (mpl::fixed_c and mpl::rational_c).

- -

But, from the user's perspective, the above example is much more verbose than the shorter, incorrect one. Thus, for the purpose of convenience, the library does provide users with a template that takes non-type template parameters, but offers a more compact notation:

- -
-typedef mpl::list_c<long,1,2,3,4,5> numbers;
-
- -

There is a similar vector counterpart as well:

- -
-typedef mpl::vector_c<long,1,2,3,4,5> numbers;
-
-
- -
-
-
-

2.3.7. A variety of sequences

-
-
- -

Previous efforts to provide generalized metaprogramming facilities for C++ have always concentrated on cons-style type lists and a few core algorithms like size and at, which are tied to the specific sequence implementation. Such systems have an elegant simplicity reminiscent of the analogous functionality in pure functional Lisp. It is much more time-consuming to implement even a basic set of the sequence algorithms provided by equivalent run-time libraries (the STL in particular), but if we have learned anything from the STL, it is that tying those algorithms' implementations to a specific sequence implementation is a misguided effort!

- -

The truth is that there is no single ‘best’ type sequence implementation for the same reasons that there will never be a single ‘best’ runtime sequence implementation. Furthermore, there are already quite a number of type list implementations in use today; and just as the STL algorithms can operate on sequences which don't come from STL containers, so the MPL algorithms are designed to work with foreign type sequences.

- -

It may be an eye-opening fact for some that type lists are not the only useful compile-time sequence. Again, the need for a variety of compile-time containers arises for the same reasons that we have lists, vectors, deques, and sets in the C++ standard library - different containers have different functional and performance characteristics which determine not only applicability and efficiency of particular algorithms, but also the expressiveness or verbosity of the code that uses them. While runtime performance is not an issue for C++ metaprograms, compilation speed is often a significant bottleneck to advanced C++ software development [Abr01].

- -

The MPL provides five built-in sequences: list, list_c (really just a list of value wrappers), vector, a randomly-accessible sequence of fixed maximum size, vector_c, and range_c, a randomly-accessible sequence of consecutive integral values. More important, however, is its ability to adapt to arbitrary sequence types. The only core operations that a sequence is required to provide in order to be used with the library algorithms are begin<> and end<> metafunctions which "return" iterators into the sequence. As with the STL, it is the iterators which are used to implement most of the general-purpose sequence algorithms the library provides. Also, as with the STL, algorithm specialization is used to take advantage of implementation knowledge about particular sequences: many of the "basic" sequence operations such as back<>, front<>, size<>, and at<> are specialized on sequence type to provide a more efficient implementation than the fully generic version.

-
- -
-
-
-

2.3.8. Loop/recursion unrolling

-
-
- -

Almost coincidentally, loop unrolling can be as important to compile-time iterative algorithms as it is to runtime algorithms. To see why, one must first remember that all "loops" in C++ metaprograms, are in fact, implemented with recursion, and that the template instantiation depth can be a valuable resource in a compiler implementation. In fact, Annex B of the C++ standard ([ISO98], annex B [limits]) recommends a minimum depth of 17 recursively nested template instantiations; but this is far too low for many serious metaprograms, some of which easily exceed the hard-coded instantiation limits of some otherwise excellent compilers. To see how this works in action, let's examine a straightforward implementation of the fold metafunction, which combines some algorithm state with each element of a sequence:

- -
-namespace aux {
-
-// unspecialized version combines the initial state and first element
-// and recurses to process the rest
-template<
-      typename Start
-    , typename Finish
-    , typename State
-    , typename BinaryFunction
-    >
-struct fold_impl
-  : fold_impl<
-        typename Start::next
-      , Finish
-      , typename apply<
-              BinaryFunction
-            , State
-            , typename Start::type
-            >::type
-      , BinaryFunction
-      >
-{
-};
-
-// specialization for loop termination
-template<
-      typename Finish
-    , typename State
-    , typename BinaryFunction
-    >
-struct fold_impl<Finish,Finish,State,BinaryFunction>
-{
-    typedef State type;
-};
-
-} // namespace aux
-
-// public interface
-template<
-      typename Sequence
-    , typename State
-    , typename ForwardOp
-    >
-struct fold
-    : aux::fold_impl<
-        , typename begin<Sequence>::type
-        , typename end<Sequence>::type
-        , State
-        , typename lambda<ForwardOp>::type
-        >
-{
-};
-
- -

Although simple and elegant, this implementation will always incur at least as many levels of recursive template instantiation as there are elements in the input sequence. 8 The library addresses this problem by explicitly "unrolling" the recursion. To apply the technique to our fold example, we begin by factoring out a single step of the algorithm. Our fold_impl_step metafunction has two results: type (the next state), and iterator (the next sequence position).

- -
-template<
-      typename BinaryFunction
-    , typename State
-    , typename Start
-    , typename Finish
-    >
-struct fold_impl_step
-{
-    typedef typename apply<
-          BinaryFunction
-        , State
-        , typename Start::type
-        >::type type;
-
-    typedef typename Start::next iterator;
-};
-
- -

As with our main algorithm implementation, we specialize for the loop termination condition so that the step becomes a no-op:

- -
-template<
-      typename BinaryFunction
-    , typename State
-    , typename Finish
-    >
-struct fold_impl_step<BinaryFunction,State,Finish,Finish>
-{
-    typedef State type;
-    typedef Finish iterator;
-};
-
- -

Now we can now reduce fold's instantiation depth by any constant factor N simply by inserting N invocations of fold_impl_step. Here we've chosen a factor of 4:

- -
-template<
-      typename Start
-    , typename Finish
-    , typename State
-    , typename BinaryFunction
-    >
-struct fold_impl
-{
- private:
-    typedef fold_impl_step<
-        BinaryFunction
-      , State
-      , Start
-      , Finish
-      > next1;
-    
-    typedef fold_impl_step<
-        BinaryFunction
-      , typename next1::type
-      , typename next1::iterator
-      , Finish
-      > next2;
-    
-    typedef fold_impl_step<
-        BinaryFunction
-      , typename next2::type
-      , typename next2::iterator
-      , Finish
-      > next3;
-    
-    typedef fold_impl_step<
-        BinaryFunction
-      , typename next3::type
-      , typename next3::iterator
-      , Finish
-      > next4;
-    
-    typedef fold_impl_step<
-          typename next4::iterator
-        , Finish
-        , typename next4::type
-        , BinaryFunction
-        > recursion;
-
- public:
-    typedef typename recursion::type type;
-};
-
- -

The MPL applies this unrolling technique across all algorithms with an unrolling factor tuned according to the demands of the C++ implementation in use, and with an option for the user to override the value. 9 This fact enables users to push beyond the metaprogramming limits they would usually encounter with more naive algorithm implementations. Experiments also show a small (up to 10%) increase in metaprogram instantiation speed on some compilers when loop unrolling is used.

-
-
-
- - - - - diff --git a/doc/paper/html/xsltproc_build.bat b/doc/paper/html/xsltproc_build.bat deleted file mode 100755 index 7e91c0b..0000000 --- a/doc/paper/html/xsltproc_build.bat +++ /dev/null @@ -1,11 +0,0 @@ -@echo off - -if "%4" == "" goto build -f:\msxsl\msxsl.exe f:\home\depot\xml\stylesheets\docbook-xsl-1.50.0\html\titlepage.templates.xml f:\home\depot\xml\stylesheets\docbook-1.50.0\template\titlepage.xsl | f:\msxsl\msxsl.exe - f:\msxsl\to_utf8.xsl -o f:\home\depot\xml\stylesheets\docbook-xsl-1.50.0\html\titlepage.templates.xsl - -:build -sx -x lower -x empty %2 >%3.xml -xsltproc -o %3 f:\home\depot\xml\stylesheets\docbook-xsl-1.50.0\html\my\%1 %3.xml -del %3.xml -f:\tidy\tidy.exe -config f:\tidy\config.txt -m %3 -f:\tidy\tidy_attr.py %3 diff --git a/doc/paper/mpl_paper.html b/doc/paper/mpl_paper.html deleted file mode 100644 index 9ca186d..0000000 --- a/doc/paper/mpl_paper.html +++ /dev/null @@ -1,1957 +0,0 @@ - - - - -The Boost C++ Metaprogramming Library - - - - - -
-
-
-
-

The Boost C++ Metaprogramming Library

-
-
- -
-
-

Aleksey Gurtovoyi and David Abrahamsii

- -
i MetaCommunications, agurtovoy@meta-comm.com
- -
ii Boost Consulting, david.abrahams@rcn.com
-
-
- -
-
-

Abstract

- -

This paper describes the Boost C++ template metaprogramming library (MPL), an extensible compile-time framework of algorithms, sequences and metafunction classes. The library brings together important abstractions from the generic and functional programming worlds to build a powerful and easy-to-use toolset which makes template metaprogramming practical enough for the real-world environments. The MPL is heavily influenced by its run-time equivalent - the Standard Template Library (STL), a part of the C++ standard library [STL94], [ISO98]. Like the STL, it defines an open conceptual and implementation framework which can serve as a foundation for future contributions in the domain. The library's fundamental concepts and idioms enable the user to focus on solutions without navigating the universe of possible ad-hoc approaches to a given metaprogramming problem, even if no actual MPL code is used. The library also provides a compile-time lambda expression facility enabling arbitrary currying and composition of class templates, a feature whose runtime counterpart is often cited as missing from the STL. This paper explains the motivation, usage, design, and implementation of the MPL with examples of its real-life applications, and offers some lessons learned about C++ template metaprogramming.

-
-
- -
-
-

Keywords: template metaprogramming, generic programming, programming languages, C++, STL, type systems, polymorphism, compile-time

-
-
-
- - - -
-
-
-

1. Introduction

-
-
- -

Metaprogramming is usually defined as the creation of programs which generate other programs. Parser generators such as YACC [Joh79] are examples of one kind of program-generating program. The input language to YACC is a context-free grammar in Extended Backus-Naur Form [EBNF], and its output is a program which parses that grammar. Note that in this case the metaprogram (YACC) is written in a language (C) which does not directly support the description of generated programs. These specifications, which we'll call metadata, are not written in C, but in a meta-language. Because the the rest of the user's program typically requires a general-purpose programming system and must interact with the generated parser, the metadata is translated into C, which is then compiled and linked together with the rest of the system. The metadata thus undergoes two translation steps, and the user is always very conscious of the boundary between her metadata and the rest of her program.

- -
-
-
-

1.1. Native language metaprogramming

-
-
- -

A more interesting form of metaprogramming is available in languages such as Scheme [SS75], where the generated program specification is given in the same language as the metaprogram itself. The metaprogrammer defines her meta-language as a subset of the expressible forms of the underlying language, and program generation can take place in the same translation step used to process the rest of the user's program. This allows users to switch transparently between ordinary programming, generated program specification, and metaprogramming, often without being aware of the transition.

-
- -
-
-
-

1.2. Metaprogramming in C++

-
-
- -

In C++, it was discovered almost by accident [Unr], [Vel95a] that the template mechanism provides a rich facility for computation at compile-time. In this section, we'll explore the basic mechanisms and some common idioms used for metaprogramming in C++.

- -
-
-
-

1.2.1. Numeric computations

-
-
- -

The availability of non-type template parameters makes it possible to perform integer computations at compile-time. For example, the following template computes the factorial of its argument:

- -
-template< unsigned n >
-struct factorial
-{
-    static const unsigned value = n * factorial<n-1>::value;
-};
-
-template<>
-struct factorial<0>
-{
-    static const unsigned value = 1;
-};
-
- -

The program fragment above is called a metafunction, and it is easy to see its relationship to a function designed to be evaluated at runtime: the “metafunction argument” is passed as a template parameter, and its “return value” is defined as a nested static constant. Because of the hard line between the expression of compile-time and runtime computation in C++, metaprograms look different from their runtime counterparts. Thus, although as in Scheme the C++ metaprogrammer writes her code in the same language as the ordinary program, only a subset of the full C++ language is available to her: those expressions which can be evaluated at compile-time. Compare the above with a straightforward runtime definition of the factorial function:

- -
-unsigned factorial(unsigned N)
-{
-    return N == 0 ? 1 : N * factorial(N - 1);
-}
-
- -

While it is easy to see the analogy between the two recursive definitions, recursion is in general more important to C++ metaprograms than it is to runtime C++. In contrast to languages such as Lisp where recursion is idiomatic, C++ programmers will typically avoid recursion when possible. This is done not only for efficiency reasons, but also because of “cultural momentum”: recursive programs are simply harder (for C++ programmers) to think about. Like pure Lisp, though, the C++ template mechanism is a functional programming language: as such it rules out the use of data mutation required to maintain loop variables.

- -

A key difference between the runtime and compile-time factorial functions is the expression of the termination condition: our meta-factorial uses template specialization as a kind of pattern-matching mechanism to describe the behavior when N is zero. The syntactic analogue in the runtime world would require two separate definitions of the same function. In this case the impact of the second definition is minimal, but in large metaprograms the cost of maintaining and understanding the terminating definitions can become significant.

- -

Note also that a C++ metafunction's return value must be named. The name chosen here, value, is the same one used for all numeric returns in the MPL. As we'll see, establishing a consistent naming convention for metafunction returns is crucial to the power of the library.

-
- -
-
-
-

1.2.2. Type computations

-
-
- -

How could we apply our factorial metafunction? We might, for example, produce an array type of an appropriate size to hold all permutations of instances of another type:

- -
-// permutation_holder<T>::type is an array type which can contain 
-// all permutations of a given T.
-
-// unspecialized template for scalars
-template< typename T >
-struct permutation_holder
-{
-    typedef T type[1][1];
-};
-
-// specialization for array types
-template< typename T, unsigned N >
-struct permutation_holder<T[N]>
-{
-    typedef T type[factorial<N>::value][N];
-};
-
- -

Here we have introduced the notion of a type computation. Like factorial above, permutation_holder template is a metafunction. However, where factorial manipulates unsigned integer values, permutation_holder accepts and “returns” a type (as the nested typedef type). Because the C++ type system provides a much richer set of expressions than anything we can use as a nontype template argument (e.g. the integers), C++ metaprograms tend to be composed mostly of type computations.

-
- -
-
-
-

1.2.3. Type sequences

-
-
- -

The ability to programmatically manipulate collections of types is a central tool of most interesting C++ metaprograms. Because this capability is so well-supported by the MPL, we'll provide just a brief introduction to the basics here. Later on, we'll revisit the example below to show how it can be implemented using MPL.

- -

First, we'd need a way to represent the collection. One idea might be to store the types in a structure:

- -
-struct types
-{
-    int t1;
-    long t2;
-    std::vector<double> t3;
-};
-
- -

Unfortunately, this arrangement is not susceptible to the compile-time type introspection power that C++ gives us: there's no way to find out what the names of the members are, and even if we assume that they're named according to some convention as above, there's no way to know how many members there are. The key to solving this problem is to increase the uniformity of the representation. If we have a consistent way to get the first type of any sequence and the rest of the sequence, we can easily access all members:

- -
-template< typename First, typename Rest >
-struct cons
-{
-    typedef First first;
-    typedef Rest rest;
-};
-
-struct nil {};
-
-typedef
-      cons<int
-    , cons<long
-    , cons<std::vector<double>
-    , nil
-    > > > my_types;
-
- -

The structure described by types above is the compile-time analogue of a singly-linked list; it has been first introduced by Czarnecki and Eisenecker in [CE98]. Now that we've adjusted the structure so that the C++ template machinery can “peel it apart”, let's examine a simple metafunction which does so. Suppose a user wished to find the largest of an arbitrary collection of types. We can apply the recursive metafunction formula which should by now be familiar:

- -
-

Example 1. 'largest' metafunction

- -
-// choose the larger of two types
-template<
-      typename T1
-    , typename T2
-    , bool choose1 = (sizeof(T1) > sizeof(T2)) // hands off!
-    >
-struct choose_larger
-{
-    typedef T1 type;
-};
-
-// specialization for the case where sizeof(T2) >= sizeof(T1)
-template< typename T1, typename T2 >
-struct choose_larger< T1,T2,false >
-{
-    typedef T2 type;
-};
-
-// get the largest of a cons-list
-template< typename T > struct largest;
-
-// specialization to peel apart the cons list
-template< typename First, typename Rest >
-struct largest< cons<First,Rest> >
-    : choose_larger< First, typename largest<Rest>::type >
-{
-    // type inherited from base
-};
-
-// specialization for loop termination
-template< typename First >
-struct largest< cons<First,nil> >
-{
-    typedef First type;
-};
-
-int main()
-{
-    // print the name of the largest of my_types
-    std::cout
-        << typeid(largest<my_types>::type).name()
-        << std::endl
-        ;
-}
-
-
- -

There are several things worth noticing about this code:

- -
-
    -
  • -

    It uses a few ad-hoc, esoteric techniques, or “hacks”. The default template argument choose1 (labeled “hands off!”) is one example. Without it, we would have needed yet another template to provide the implementation of choose_larger, or we would have had to provide the computation explicitly as a parameter to the template - perhaps not bad for this example, but it would make choose_larger much less useful and more error-prone. The other hack is the derivation of a specialization of largest from choose_larger. This is a code-saving device which allows the programmer to avoid writing “typedef typename ...::type type” in the template body.

    -
  • - -
  • -

    Even this simple metaprogram uses three separate partial specializations. The largest metafunction uses two specializations. One might expect that this indicates there are two termination conditions, but there are not: one specialization is needed simply to deal with access to the sequence elements. These specializations make the code difficult to read by spreading the definition of a single metafunction over several C++ template definitions. Also, because they are partial specializations, they make the code unusable for a large community of C++ programmers whose compilers don't support that feature.

    -
  • -
-
- -

While these techniques are, of course, a valuable part of the arsenal of any good C++ metaprogrammer, their use tends to make programs written in what is already an unusual style harder-to-read and harder-to-write. By encapsulating commonly-used structures and dealing with loop terminations internally, the MPL reduces the need for both tricky hacks and for template specializations.

-
-
- -
-
-
-

1.3. Why metaprogramming?

-
-
- -

It's worth asking why anyone would want to do this. After all, even a simple toy example like the factorial metafunction is somewhat esoteric. To show how the type computation can be put to work, let's examine a simple example. The following code produces an array containing all possible permutations of another array:

- -
-// can't return an array in C++, so we need this wrapper
-template< typename T >
-struct wrapper
-{
-    T x;
-};
-
-// return an array of the N! permutations of 'in'
-template< typename T >
-wrapper< typename permutation_holder<T>::type >
-all_permutations(T const& in)
-{
-    wrapper<typename permutation_holder<T>::type> result;
-
-    // copy the unpermutated array to the first result element
-    unsigned const N = sizeof(T) / sizeof(**result.x);
-    std::copy(&*in, &*in + N, result.x[0]);
-
-    // enumerate the permutations
-    unsigned const result_size = sizeof(result.x) / sizeof(T);
-    for (T* dst = result.x + 1; dst != result.x + result_size; ++dst)
-    {
-        T* src = dst - 1;
-        std::copy(*src, *src + N, *dst);
-        std::next_permutation(*dst, *dst + N);
-    }
-    return result;
-}
-
- -

The runtime definition of factorial would be useless in all_permutations above, since in C++ the sizes of array members must be computed at compile-time. However, there are alternative approaches; how could we avoid metaprogramming, and what would the consequences be?

- -
-
    -
  1. -

    We could write programs to interpret the metadata directly. In our factorial example, the array size could have been a runtime quantity; then we'd have been able to use the straightforward factorial function. However, that would imply the use of dynamic allocation, which is often expensive.

    - -

    To carry this further, YACC might be rewritten to accept a pointer-to-function returning tokens from the stream to be parsed, and a string containing the grammar description. This approach, however, would impose unacceptable runtime costs for most applications: either the parser would have to treat the grammar nondeterministically, exploring the grammar for each parse, or it would have to begin by replicating at runtime the substantial table-generation and optimization work of the existing YACC for each input grammar.

    -
  2. - -
  3. -

    We could replace the compile-time computation with our own analysis. After all, the size of arrays passed to all_permutations are always known at compile-time, and thus can be known to its user. We could ask the user to supply the result type explicitly:

    - -
    -template< typename Result, typename T >
    -Result all_permutations(T const& input);
    -
    - -

    The costs to this approach are obvious: we give up expressivity (by requiring the user to explicitly specify implementation details), and correctness (by allowing the user to specify them incorrectly). Anyone who has had to write parser tables by hand will tell you that the impracticality of this approach is the very reason of YACC's existence.

    - -

    In a language such as C++, where the metadata can be expressed in the same language as the rest of the user's program, expressivity is further enhanced: the user can invoke metaprograms directly, without learning a foreign syntax or interrupting the flow of her code.

    -
  4. -
-
- -

So, the motivation for metaprogramming comes down to the combination of three factors: efficiency, expressivity, and correctness. While in classical programming there is always a tension between expressivity and correctness on one hand and efficiency on the other, in the metaprogramming world we wield new power: we can move the computation required for expressivity from runtime to compile-time.

-
- -
-
-
-

1.4. Why a metaprogramming library?

-
-
- -

One might just as well ask why we need any generic library:

- -
-
    -
  • -

    Quality. Code that is appropriate for a general-purpose library is usually incidental to the purpose of its users. To a library developer, it is the central mission. On average, the containers and algorithms provided by any given C++ standard library implementation are more-flexible and better-implemented than the project-specific implementations which abound, because library development was treated as an end in itself rather than a task incidental to the development of some other application. With a centralized implementation for any given function, optimizations and improvements are more likely to have been applied.

    -
  • - -
  • -

    Re-use. More important even than the re-use of code which all libraries provide, a well-designed generic library establishes a framework of concepts and idioms which establishes a reusable mental model for approaching problems. Just as the C++ Standard Template Library gave us iterator concepts and a function object protocol, the Boost Metaprogramming Library provides type-iterators and metafunction class protocol. A well-considered framework of idioms saves the metaprogrammer from considering irrelevant implementation details and allows her to concentrate on the problem at hand.

    -
  • - -
  • -

    Portability. A good library can smooth over the ugly realities of platform differences. While in theory a metaprogramming library is fully generic and shouldn't be concerned with these issues, in practice support for templates remains inconsistent even four years after standardization. This should perhaps not be surprising: C++ templates are the language's furthest-reaching and most complicated feature, which largely accounts for the power of metaprogramming in C++.

    -
  • - -
  • -

    Fun. Repeating the same idioms over and over is tedious. It makes programmers tired and reduces productivity. Furthermore, when programmers get bored they get sloppy, and buggy code is even more costly than slowly-written code. Often the most useful libraries are simply patterns that have been “plucked” by an astute programmer from a sea of repetition. The MPL helps to reduce boredom by eliminating the need for the most commonly-repeated boilerplate coding patterns.

    -
  • -
-
- -

As one can see, the MPL's development is motivated primarily by the same practical, real-world considerations that justify the development of any other library. Perhaps this is an indication that template metaprogramming is finally ready to leave the realm of the esoteric and enter the lingua franca of every day programmers.

-
-
- -
-
-
-

2. Basic usage

-
-
- -
-
-
-

2.1. Conditional type selection

-
-
- -

Conditional type selection is the simplest basic construct of C++ template metaprogramming. Veldhuizen [Vel95a] was the first to show how to implement it, and Czarnecki and Eisenecker [CE00] first presented it as a standalone library primitive. The MPL defines the corresponding facility as follows:

- -
-template<
-      typename Condition
-    , typename T1
-    , typename T2
-    >
-struct if_
-{
-    typedef /*unspecified*/ type;
-};
-
- -

Note that the first template parameter of the template is a type.

- -
-// usage/semantics
-typedef mpl::if_<mpl::true_c,char,long>::type t1;
-typedef mpl::if_<mpl::false_c,char,long>::type t2;
-
-BOOST_MPL_ASSERT_IS_SAME(t1, char);
-BOOST_MPL_ASSERT_IS_SAME(t2, long);
-
- -

The construct is important because template metaprograms often contain a lot of decision-making code, and, as we will show, spelling it manually every time via (partial) class template specialization quickly becomes impractical. The template is also important from the point of encapsulating the compiler workarounds.

- -
-
-
-

2.1.1. Delayed evaluation

-
-
- -

The way the C++ template instantiation mechanism works imposes some subtle limitations on applicability of the type selection primitive (if_), compared to a manually implemented equivalent of the selection code. For example, suppose we are implementing a pointed_type traits template such that pointed_type<T>::type instantiated for a T that is either a plain pointer (U*), std::auto_ptr<U>, or any of the Boost smart pointers [SPL], e.g. boost::scoped_ptr<U>, will give us the pointed type (U):

- -
-BOOST_MPL_ASSERT_IS_SAME(pointed_type<my*>::type, my);
-BOOST_MPL_ASSERT_IS_SAME(pointed_type< std::auto_ptr<my> >::type, my);
-BOOST_MPL_ASSERT_IS_SAME(pointed_type< boost::scoped_ptr<my> >::type, my);
-
- -

Unfortunately, the straightforward application of if_ to this problem does not work: 1

- -
-template< typename T >
-struct pointed_type
-    : mpl::if_<
-          boost::is_pointer<T>
-        , typename boost::remove_pointer<T>::type
-        , typename T::element_type // #1
-        >
-{
-};
-
-// the following code causes compilation error in line #1:
-// name followed by "::" must be a class or namespace name
-typedef pointed_type<char*>::type result;
-
- -

Clearly, the expression typename T::element_type is not valid in the case of T == char*, and that's what the compiler is complaining about. Implementing the selection code manually solves the problem:

- -
-namespace aux {
-// general case
-template< typename T, bool is_pointer = false >
-struct select_pointed_type
-{
-    typedef typename T::element_type type;
-};
-
-// specialization for plain pointers
-template< typename  T >
-struct select_pointed_type<T,true>
-{
-    typedef typename boost::remove_pointer<T>::type type;
-};
-}
-
-template< typename T >
-struct pointed_type
-   : aux::select_pointed_type<
-          T, boost::is_pointer<T>::value
-        >
-{
-};
-
- -

But this quickly becomes awkward if needs to be done repeatedly, and this awkwardness is compounded when partial specialization is not available. We can try to work around the problem as follows:

- -
-namespace aux {
-template< typename T >
-struct element_type
-{
-     typedef typename T::element_type type;
-};
-}
-
-template< typename T >
-struct pointed_type
-{
-    typedef typename mpl::if_<
-          boost::is_pointer<T>
-        , typename boost::remove_pointer<T>::type
-        , typename aux::element_type<T>::type
-        >::type type;
-};
-
- -

but this doesn't work either - the access to the aux::element_type<T>'s nested type member still forces the compiler to instantiate element_type<T> with T == char*, and that instantiation is, of course, invalid. Also, although in our case this does not lead to a compile error, the boost::remove_pointer<T> template always gets instantiated as well, and for the same reason (because we are accessing its nested type member). Unnecessary instantiation that is not fatal may or may be not a problem, depending on the “weight” of the template (how much the instantiation taxes the compiler), but a general rule of thumb would be to avoid such code.

- -

Returning to our error, to make the above code compile, we need to factor the act of “asking” aux::element_type<T> for its nested type out of the if_ invocation. The fact that both the boost::remove_pointer<T> trait template and aux::element_type<T> use the same naming convention for their result types makes the refactoring easier:

- -
-template< typename T >
-struct pointed_type
-{
- private:
-    typedef typename mpl::if_<
-          boost::is_pointer<T>
-        , boost::remove_pointer<T>
-        , aux::element_type<T>
-        >::type func_;
-
- public:
-    typedef typename func_::type type;
-};
-
- -

Now the compiler is guaranteed not to instantiate both boost::remove_pointer<T> and aux::element_type<T>, even although they are used as actual parameters to the if_ template, so we are allowed to get away with aux::element_type<char*> so long as it won't end up being selected as func_.

- -

The above technique is so common in template metaprograms, that it even makes sense to facilitate the selection of a nested type member by introducing a high-level equivalent to if_ - the one that will do the func_::type operation (that is called [nullary] metafunction class application) as a part of its invocation. The MPL provides such template - it's called apply_if. Using it, we can re-write the above code as simple as:

- -
-template< typename T >
-struct pointed_type
-{
-    typedef typename mpl::apply_if<
-          boost::is_pointer<T>
-        , boost::remove_pointer<T>
-        , aux::element_type<T>
-        >::type type;
-};
-
- -

To make our techniques review complete, let's consider a slightly different example - suppose we want to define a high-level wrapper around boost::remove_pointer traits template [TTL], which will strip the pointer qualification conditionally. We will call it remove_pointer_if:

- -
-template<
-      typename Condition
-    , typename T
-    >
-struct remove_pointer_if
-{
-    typedef typename mpl::if_<
-          Condition
-        , typename boost::remove_pointer<T>::type
-        , T
-        >::type type;
-};
-
- -

Now the above works the first time, but it suffers from the problem we mentioned earlier - boost::remove_pointer<T> gets instantiated even if its result is never used. In the metaprogramming world compilation time is an important resource [Abr01], and it is wasted by unnecessary template instantiations. We've just seen how to deal with the problem when both arguments to if_ are the results of nullary metafunction class applications, but in this example one of the arguments (T) is just a simple type, so the refactoring just doesn't seem possible.

- -

The easiest way out of this situation would be to pass to if_ a real nullary metafunction instead of T - the one that returns T on its invocation. The MPL provides a simple way to do it - we just substitute identity<T> and apply_if for T and if_:

- -
-template<
-      typename Condition
-    , typename T
-    >
-struct remove_pointer_if
-{
-    typedef typename mpl::apply_if<
-          Condition
-        , boost::remove_pointer<T>
-        , mpl::identity<T>
-        >::type type;
-};
-
- -

which gives us exactly what we wanted.

-
-
- -
-
-
-

2.2. Metafunctions

-
-
- -
-
-
-

2.2.1. The simple form

-
-
- -

In C++, the basic underlying language construct which allows parameterized compile-time computation is the class template ([ISO98], section 14.5.1 [temp.class]). A bare class template is the simplest possible model we could choose for metafunctions: it can take types and/or non-type arguments as actual template parameters, and instantiation “returns” a new type. For example, the following produces a type derived from its arguments:

- -
-template< typename T1, typename T2 >
-struct derive : T1, T2
-{
-};
-
- -

However, this model is far too limiting: it restricts the metafunction result not only to class types, but to instantiations of a given class template, to say nothing of the fact that every metafunction invocation introduces an additional level of template nesting. While that might be acceptable for this particular metafunction, any model which prevented us from “returning”, say, int is obviously not general enough. To meet this basic requirement, we must rely on a nested type to provide our return value:

- -
-template< typename T1, typename T2 >
-struct derive
-{
-    struct type : N1, N2 {};
-};
-
-// silly specialization, but demonstrates "returning" int
-template<>
-struct derive<void,void>
-{
-    typedef int type;
-};
-
- -

Veldhuizen [Vel95a] was first to talk about class templates of this form as “compile-time functions”, and Czarnecki and Eisenecker [CE00] have introduced “template metafunction” as an equivalent term (they also use the simpler term “metafunction”, as do we). Czarnecki and Eisenecker have also recognized the limitations of the simple metafunction representation and suggested the form that we discuss in Section 2.2.3.

-
- -
-
-
-

2.2.2. Higher-order metafunctions

-
-
- -

While syntactically simple, the simple template metafunction form does not always interact optimally with the rest of C++. In particular, the simple metafunction form makes it unnecessarily awkward and tedious to define and work with higher-order metafunctions (metafunctions that operate on other metafunctions). In order to pass a simple metafunction to another template, we need to use template template parameters:

- -
-// returns F(T1,F(T2,T3))
-template<
-      template<typename> class F
-    , typename T1
-    , typename T2
-    , typename T3
-    >
-struct apply_twice
-{
-  typedef typename F<
-        T1
-      , typename F<T2,T3>::type
-      >::type type;
-};
-
-// a new metafunction returning a type derived from T1, T2, and T3
-template<
-      typename T1
-    , typename T2
-    , typename T3
-    >
-struct derive3
-    : apply_twice<derive,T1,T2,T3>
-{
-};
-
- -

This looks different, but it seems to work. 2 However, things begin to break down noticeably when we want to “return” a metafunction from our metafunction:

- -
-// returns G s.t. G(T1,T2,T3) == F(T1,F(T2,T3))
-template< template<typename> class F >
-struct compose_self
-{
-    template<
-          typename T1
-        , typename T2
-        , typename T3
-        > 
-    struct type
-        : apply_twice<F,T1,T2,T3>
-    {
-    };
-};
-
- -

The first and most obvious problem is that the result of applying compose_self is not itself a type, but a template, so it can't be passed in the usual ways to other metafunctions. A more subtle issue, however, is that the metafunction “returned” is not exactly what we intended. Although it acts just like apply_twice, it differs in one important respect: its identity. In the C++ type system, compose_self<F>::template type<T,U,V> is not a synonym for apply_twice<F,T,U,V>, and any metaprogram which compared metafunctions would discover that fact.

- -

Because C++ makes a strict distinction between type and class template template parameters, reliance on simple metafunctions creates a “wall” between metafunctions and metadata, relegating metafunctions to the status of second-class citizens. For example, recalling our introduction to type sequences, there's no way to make a cons list of metafunctions:

- -
-typedef cons<derive, cons<derive3, nil> > derive_functions; // error!
-
- -

We might consider redefining our cons cell so we can pass derive as the head element:

- -
-template <
-      template< template<typename T, typename U> class F
-    , typename Tail
-    >
-struct cons;
-
- -

However, now we have another problem: C++ templates are polymorphic with respect to their type arguments, but not with respect to template template parameters. The arity (number of parameters) of any template template parameter is strictly enforced, so we still can't embed derive3 in a cons list. Moreover, polymorphism between types and metafunctions is not supported (the compiler expects one or the other), and as we've seen, the syntax and semantics of “returned” metafunctions is different from that of returned types. Trying to accomplish everything with the simple template metafunction form would seriously limit the applicability of higher-order metafunctions and would have an overall negative effect on the both conceptual and implementation clarity, simplicity and size of the library.

-
- -
-
-
-

2.2.3. Metafunction classes

-
-
- -

Fortunately, the truism that “there is no problem in software which can't be solved by adding yet another level of indirection” applies here. To elevate metafunctions to the status of first-class objects, the MPL introduces the concept of a “metafunction class”:

- -
-// metafunction class form of derive
-struct derive
-{
-    template< typename N1, typename N2 >
-    struct apply
-    {
-        struct type : N1, N2 {};
-    };
-};
-
- -

This form should look familiar to anyone acquainted with function objects in STL, with the nested apply template taking the same role as the runtime function-call operator. In fact, compile-time metafunction classes have the same relationship to metafunctions that runtime function objects have to functions:

- -
-// function form of add
-template< typename T > T add(T x, T y) { return x + y; }
-
-// function object form of add
-struct add
-{
-    template< typename T >
-    T operator()(T x, T y) { return x + y; }
-};
-
-
- -
-
-
-

2.2.4. One size fits all?

-
-
- -

The metafunction class form solves all the problems with ordinary template metafunction mentioned earlier: since it is a regular class, it can be placed in compile-time metadata sequences and manipulated by other metafunctions using the same protocols as for any other metadata. We thereby avoid the code-duplication needed to provide versions of each library component to operate on ordinary metadata and on metafunctions with each distinct supported arity.

- -

On the other hand, it seems that accepting metafunction classes as the representation for compile-time function entities imposes code duplication danger as well: if the library's own primitives, algorithms, etc. are represented as class templates, that means that one either cannot reuse these algorithms in the context of higher-order functions, or she have to duplicate all algorithms in the second form, so, for instance, there would be two versions of find:

- -
-// user-friendly form
-template<
-      typename Sequence
-    , typename T
-    >
-struct find
-{
-    typedef /* ... */ type;
-};
-
-// "metafunction class" form
-struct find_func
-{
-    template< typename Sequence, typename T >
-    struct apply
-    {
-        typedef /* ... */ type;
-    };
-};
-
- -

Of course, the third option is to eliminate “user-friendly form” completely so one would always have to write:

- -
-typedef mpl::find::apply<list,long>::type iter;
-// or, if one prefers,
-// typedef mpl::apply< mpl::find,list,long >::type iter;
-
- -

instead of

- -
-typedef mpl::find<list,long>::type iter;
-
- -

That too would hurt usability, considering that the direct invocations of library's algorithms are far more often-used than passing algorithms as arguments to other algorithms/metafunctions.

-
- -
-
-
-

2.2.5. From metafunction to metafunction class

-
-
- -

The MPL's answer to this dilemma is lambda expressions. Lambda is the mechanism that enables the library to curry metafunctions and convert them into metafunction classes, so when one wants to pass the find algorithm as an argument to a higher-order metafunction, she just write:

- -
-using namespace mpl::placeholder;
-typedef mpl::apply< my_f, mpl::find<_1,_2> >::type result;
-
- -

where _1 and _2 are placeholders for the first and second arguments to the resulting metafunction class. This preserves the intuitive syntax below for when the user wants to use find directly in her code:

- -
-typedef mpl::find<list,long>::type iter;
-
- -

Lambda facility is described in more details in Section 3.

-
-
- -
-
-
-

2.3. Sequences, algorithms, and iterators

-
-
- -
-
-
-

2.3.1. Introduction

-
-
- -

Compile-time iteration over a sequence (of types) is one of the basic concepts of template metaprogramming. Differences in types of objects being manipulated is the most common point of variability of similar but not identical code/design, and such designs are the direct target for some metaprogramming. Templates were originally designed to solve this exact problem (e.g. std::vector). However, without predefined abstractions/constructs for manipulating/iterating over sequences of types (as opposed to standalone types), and without known techniques for emulating these constructs using the current language facilities, their effect on helping high-level metaprogramming happen has been limited.

- -

Czarnecki and Eisenecker [CE98], [CE00] were the first to introduce compile-time sequences of types and some simple algorithms on them, although the idea of representing common data structures like trees, lists, etc. at compile time, using class template composition has been around for a while (e.g. most of the expression template libraries build such trees as a part of their expression "parsing" process [Vel95b]). Alexandrescu [Ale01] used lists of types and some algorithms on them to implement several design patterns; the accompanying code is known as the Loki library [Loki].

-
- -
-
-
-

2.3.2. Algorithms and sequences

-
-
- -

Most of the algorithms in the Boost Metaprogramming Library operate on sequences. For example, searching for a type in a list looks like this:

- -
-typedef mpl::list<char,short,int,long,float,double> types;
-typedef mpl::find<types,long>::type iter;
-
- -

Here, find accepts two parameters - a sequence to search (types) and the type to search for (long) - and returns an iterator iter pointing to the first element of the sequence such that iter::type is identical to long. If no such element exists, iter is identical to end<types>::type. Basically, this is how one would search for a value in a std::list or std::vector, except that mpl::find accepts the sequence as a single parameter, while std::find takes two iterators. Everything else is pretty much the same - the names are the same, the semantics are very close, there are iterators, and one can search not only by type, but also by using a predicate:

- -
-typedef mpl::find_if< types,boost::is_float<_> >::type iter;
-
- -

This conceptual/syntactical similarity with the STL is not coincidental. Reusing the conceptual framework of the STL in the compile-time world allows us to apply familiar and sound approaches for dealing with sequential data structures. The algorithms and idioms which programmers already know from the STL can be applied again at compile-time. We consider this to be one of MPL's greatest strengths, distinguishing it from earlier attempts to build a template metaprogramming library.

-
- -
-
-
-

2.3.3. Sequence concepts

-
-
- -

In the find example above, we searched for the type in a sequence built using the mpl::list template; but list is not the only sequence that the library provides. Neither is mpl::find or any other algorithm hard-coded to work only with list sequences. list is just one model of MPL's Forward Sequence concept, and find works with anything that satisfies this concept's requirements. The hierarchy of sequence concepts in MPL is quite simple - a Sequence is any compile-time entity for which begin<> and end<> produce iterators to the range of its elements; a Forward Sequence is a Sequence whose iterators satisfy Forward Iterator requirements; a Bidirectional Sequence is a Forward Sequence whose iterators satisfy Bidirectional Iterator requirements; finally, a Random Access Sequence is a Bidirectional Sequence whose iterators satisfy Random Access Iterator requirements. 3

- -

Decoupling algorithms from particular sequence implementations (through iterators) allows a metaprogrammer to create her own sequence types and to retain the rest of the library at her disposal. For example, one can define a tiny_list for dealing with sequences of three types as follows:

- -
-template< typename TinyList, long Pos >
-struct tiny_list_item;
-
-template< typename TinyList, long Pos >
-struct tiny_list_iterator
-{
-    typedef typename tiny_list_item<TinyList,Pos>::type type;
-    typedef tiny_list_iterator<TinyList, Pos-1> prior;
-    typedef tiny_list_iterator<TinyList, Pos+1> next;
-};
-
-template< typename T0, typename T1, typename T2 >
-struct tiny_list
-{
-    typedef tiny_list_iterator<tiny_list, 0> begin;
-    typedef tiny_list_iterator<tiny_list, 3> end;
-    typedef T0 type0;
-    typedef T1 type1;
-    typedef T2 type2;
-};
-
-template< typename TinyList >
-struct tiny_list_item<TinyList,0>
-{
-    typedef typename TinyList::type0 type;
-};
-
-template< typename TinyList >
-struct tiny_list_item<TinyList,1>
-{
-    typedef typename TinyList::type1 type;
-};
-
-template< typename TinyList >
-struct tiny_list_item<TinyList,2>
-{
-    typedef typename TinyList::type2 type;
-};
-
- -

and then use it with any of the library algorithms as if it were mpl::list:

- -
-typedef tiny_list< char,short,int > types;
-typedef mpl::transform<
-      types
-    , boost::add_pointer<_1>
-    >::type pointers;
-
- -

Note that tiny_list is a model of Bidirectional Sequence; it would be a Random Access Sequence if we added advance and distance members to tiny_list_iterator:

- -
-template< typename TinyList, long Pos >
-struct tiny_list_iterator
-{
-    static long const position = Pos;
-
-    typedef typename tiny_list_item<TinyList,Pos>::type type;
-    typedef tiny_list_iterator<TinyList, Pos-1> prior;
-    typedef tiny_list_iterator<TinyList, Pos+1> next;
-
-    template< typename N > struct advance
-    {
-        typedef tiny_list_iterator<
-              TinyList
-            , Pos + N::value
-            > type;
-    };
-
-    template< typename Other > struct distance
-    {
-        typedef mpl::integral_c<
-              long
-            , Other::position - position
-            > type;
-    };
-};
-
- -

While the tiny_list itself might be not that interesting (after all, it can hold only three elements), if the technique above could be automated so we would be able to define not-so-tiny sequences (with five, ten, twenty, etc. elements), it would be very valuable. 4

- -

External code generation is an option, but there exists a solution within the language. However, it is not a template metaprogramming, but rather preprocessor metaprogramming. In fact, MPL's vector - a fixed-size type sequence that provides random-access iterators - is implemented very much like the above tiny_list - using the Boost Preprocessor library [PRE].

-
- -
-
-
-

2.3.4. Ad hoc example revisited

-
-
- -

So, the library provides its users with almost complete compile-time equivalent of the STL framework. Does it help them to solve their metaprogramming tasks? Let's return to our earlier largest example to see if we can rewrite it in a better way with what MPL has to offer. Well, actually, there is not much to look at, because the MPL implementation is a one-liner (we'll spread it out here for readability) 5 :

- -
-template< typename Sequence >
-struct largest
-{
-    typedef typename mpl::max_element<
-          Sequence
-          mpl::less<
-              mpl::size_of<_1>
-            , mpl::size_of<_2>
-            >
-        >::type iter;
-
-    typedef typename iter::type type;
-};
-
- -

There are no more termination conditions with tricky pattern matching, no more partial specializations; and even more importantly, it's obvious what the above code does - even although it's all templates - something that one could not say about the original version.

-
- -
-
-
-

2.3.5. iter_fold as the main iteration algorithm

-
-
- -

For the purpose of examining a little bit more of the library's internal structure, let's look at how max_element from the above example is implemented. One might expect that now we will again see all these awkward partial specializations, esoteric pattern matching, etc. Well, let's see:

- -
-template<
-      typename Sequence
-    , typename Predicate
-    >
-struct max_element
-{
-    typedef typename mpl::iter_fold<    
-          Sequence
-        , typename mpl::begin<Sequence>::type
-        , if_< less< deref<_1>,deref<_2> >, _2, _1 >
-        >::type type;
-};
-
- -

The first thing to notice here is that this algorithm is implemented in terms of another one: iter_fold. In fact, this is probably the most important point of the example, because nearly all other generic sequence algorithms in the library are implemented in terms of iter_fold. If a user should ever need to implement her own sequence algorithm, she'll almost certainly be able to do so using this primitive, which means she won't have to resort to implementing hand-crafted iteration, pattern matching of special cases for loop termination, or workarounds for lack of partial specialization. It also means that her algorithm will automatically benefit from any optimizations the library has implemented, (e.g. recursion unrolling), and that it will work with any sequence that is a model of ForwardSequence, because iter_fold does not require anything more of its sequence argument.

- -

iter_fold algorithm is basically a compile-time equivalent of the fold or reduce functions that comprise the basic and well-known primitives of many functional programming languages. An analogy more familiar to a C++ programmer would be the std::accumulate algorithm from the C++ standard library ([ISO98], section 26.4.1 [lib.accumulate]). However, iter_fold is designed to take advantage of the natural characteristics of recursive traversal: it accepts two metafunction class arguments, the first of which is applied to the state "on the way in" and the second of which is applied "on the way out".

- -

The interface to iter_fold is defined in MPL as follows:

- -
-template<
-      typename Sequence
-    , typename InitialState
-    , typename ForwardOp
-    , typename BackwardOp = _1
-    >
-struct iter_fold
-{
-    typedef /*unspecified*/ type;
-};
-
- -

The algorithm “returns” the result of two-way successive applications of binary ForwardOp and BackwardOp operations to iterators in range [begin<Sequence>::type, end<Sequence>::type) and previous result of an operation; the InitialState is logically placed before the sequence and included in the forward traversal. The result type is identical to InitialState if the sequence is empty.

- -

The library also provides iter_fold_backward, fold, and fold_backward algorithms which wrap iter_fold to accommodate its most common usage patterns.

-
- -
-
-
-

2.3.6. Sequences of numbers

-
-
- -

What we've seen so far were sequences (and algorithms on sequences) of types. It is both possible and easy to manipulate compile-time values using the library as well. The only thing to remember is that in C++, class template non-type template parameters give us one more example of non-polymorphic behavior. In other words, if one declared a metafunction to take a non-type template parameter (e.g. long) it's not possible to pass anything besides compile-time integral constants to it:

- -
-template< long N1, long N2 >
-struct equal_to
-{
-    static bool const value = (N1 == N2);
-};
-
-equal_to<5,5>::value; // ok
-equal_to<int,int>::value; // error!
-
- -

And of course this doesn't work the other way around either:

- -
-typedef mpl::list<1,2,3,4,5> numbers; // error!
-
- -

While this may be an obvious limitation, it imposes yet another dilemma on the library design: on the one hand, we don't want to restrict users to type manipulations only, and on the other hand, full support for integral manipulations would require at least duplication of most of the library facilities 6 - the same situation as we would have if we had chosen to represent metafunctions as ordinary class templates. The solution for this issue is the same as well: we represent integral values by wrapping them in types 7 . For example, to create a list of numbers one can write:

- -
-typedef mpl::list<
-      mpl::int_c<1>
-    , mpl::int_c<2>
-    , mpl::int_c<3>
-    , mpl::int_c<4>
-    , mpl::int_c<5>
-    > numbers;
-
- -

Wrapping integral constants into types to make them first-class citizens is important well inside metaprograms, where one often doesn't know (and doesn't care) if the metafunctions she is using operate on types, integral values, other metafunctions, or something else, like fixed-point or rational numbers (mpl::fixed_c and mpl::rational_c).

- -

But, from the user's perspective, the above example is much more verbose than the shorter, incorrect one. Thus, for the purpose of convenience, the library does provide users with a template that takes non-type template parameters, but offers a more compact notation:

- -
-typedef mpl::list_c<long,1,2,3,4,5> numbers;
-
- -

There is a similar vector counterpart as well:

- -
-typedef mpl::vector_c<long,1,2,3,4,5> numbers;
-
-
- -
-
-
-

2.3.7. A variety of sequences

-
-
- -

Previous efforts to provide generalized metaprogramming facilities for C++ have always concentrated on cons-style type lists and a few core algorithms like size and at, which are tied to the specific sequence implementation. Such systems have an elegant simplicity reminiscent of the analogous functionality in pure functional Lisp. It is much more time-consuming to implement even a basic set of the sequence algorithms provided by equivalent run-time libraries (the STL in particular), but if we have learned anything from the STL, it is that tying those algorithms' implementations to a specific sequence implementation is a misguided effort!

- -

The truth is that there is no single “best” type sequence implementation for the same reasons that there will never be a single “best” runtime sequence implementation. Furthermore, there are already quite a number of type list implementations in use today; and just as the STL algorithms can operate on sequences which don't come from STL containers, so the MPL algorithms are designed to work with foreign type sequences.

- -

It may be an eye-opening fact for some that type lists are not the only useful compile-time sequence. Again, the need for a variety of compile-time containers arises for the same reasons that we have lists, vectors, deques, and sets in the C++ standard library - different containers have different functional and performance characteristics which determine not only applicability and efficiency of particular algorithms, but also the expressiveness or verbosity of the code that uses them. While runtime performance is not an issue for C++ metaprograms, compilation speed is often a significant bottleneck to advanced C++ software development [Abr01].

- -

The MPL provides five built-in sequences: list, list_c (really just a list of value wrappers), vector, a randomly-accessible sequence of fixed maximum size, vector_c, and range_c, a randomly-accessible sequence of consecutive integral values. More important, however, is its ability to adapt to arbitrary sequence types. The only core operations that a sequence is required to provide in order to be used with the library algorithms are begin<> and end<> metafunctions which "return" iterators into the sequence. As with the STL, it is the iterators which are used to implement most of the general-purpose sequence algorithms the library provides. Also, as with the STL, algorithm specialization is used to take advantage of implementation knowledge about particular sequences: many of the "basic" sequence operations such as back<>, front<>, size<>, and at<> are specialized on sequence type to provide a more efficient implementation than the fully generic version.

-
- -
-
-
-

2.3.8. Loop/recursion unrolling

-
-
- -

Almost coincidentally, loop unrolling can be as important to compile-time iterative algorithms as it is to runtime algorithms. To see why, one must first remember that all "loops" in C++ metaprograms, are in fact, implemented with recursion, and that the template instantiation depth can be a valuable resource in a compiler implementation. In fact, Annex B of the C++ standard ([ISO98], annex B [limits]) recommends a minimum depth of 17 recursively nested template instantiations; but this is far too low for many serious metaprograms, some of which easily exceed the hard-coded instantiation limits of some otherwise excellent compilers. To see how this works in action, let's examine a straightforward implementation of the fold metafunction, which combines some algorithm state with each element of a sequence:

- -
-namespace aux {
-
-// unspecialized version combines the initial state and first element
-// and recurses to process the rest
-template<
-      typename Start
-    , typename Finish
-    , typename State
-    , typename BinaryFunction
-    >
-struct fold_impl
-  : fold_impl<
-        typename Start::next
-      , Finish
-      , typename apply<
-              BinaryFunction
-            , State
-            , typename Start::type
-            >::type
-      , BinaryFunction
-      >
-{
-};
-
-// specialization for loop termination
-template<
-      typename Finish
-    , typename State
-    , typename BinaryFunction
-    >
-struct fold_impl<Finish,Finish,State,BinaryFunction>
-{
-    typedef State type;
-};
-
-} // namespace aux
-
-// public interface
-template<
-      typename Sequence
-    , typename State
-    , typename ForwardOp
-    >
-struct fold
-    : aux::fold_impl<
-        , typename begin<Sequence>::type
-        , typename end<Sequence>::type
-        , State
-        , typename lambda<ForwardOp>::type
-        >
-{
-};
-
- -

Although simple and elegant, this implementation will always incur at least as many levels of recursive template instantiation as there are elements in the input sequence. 8 The library addresses this problem by explicitly "unrolling" the recursion. To apply the technique to our fold example, we begin by factoring out a single step of the algorithm. Our fold_impl_step metafunction has two results: type (the next state), and iterator (the next sequence position).

- -
-template<
-      typename BinaryFunction
-    , typename State
-    , typename Start
-    , typename Finish
-    >
-struct fold_impl_step
-{
-    typedef typename apply<
-          BinaryFunction
-        , State
-        , typename Start::type
-        >::type type;
-
-    typedef typename Start::next iterator;
-};
-
- -

As with our main algorithm implementation, we specialize for the loop termination condition so that the step becomes a no-op:

- -
-template<
-      typename BinaryFunction
-    , typename State
-    , typename Finish
-    >
-struct fold_impl_step<BinaryFunction,State,Finish,Finish>
-{
-    typedef State type;
-    typedef Finish iterator;
-};
-
- -

Now we can now reduce fold's instantiation depth by any constant factor N simply by inserting N invocations of fold_impl_step. Here we've chosen a factor of 4:

- -
-template<
-      typename Start
-    , typename Finish
-    , typename State
-    , typename BinaryFunction
-    >
-struct fold_impl
-{
- private:
-    typedef fold_impl_step<
-        BinaryFunction
-      , State
-      , Start
-      , Finish
-      > next1;
-    
-    typedef fold_impl_step<
-        BinaryFunction
-      , typename next1::type
-      , typename next1::iterator
-      , Finish
-      > next2;
-    
-    typedef fold_impl_step<
-        BinaryFunction
-      , typename next2::type
-      , typename next2::iterator
-      , Finish
-      > next3;
-    
-    typedef fold_impl_step<
-        BinaryFunction
-      , typename next3::type
-      , typename next3::iterator
-      , Finish
-      > next4;
-    
-    typedef fold_impl_step<
-          typename next4::iterator
-        , Finish
-        , typename next4::type
-        , BinaryFunction
-        > recursion;
-
- public:
-    typedef typename recursion::type type;
-};
-
- -

The MPL applies this unrolling technique across all algorithms with an unrolling factor tuned according to the demands of the C++ implementation in use, and with an option for the user to override the value. 9 This fact enables users to push beyond the metaprogramming limits they would usually encounter with more naive algorithm implementations. Experiments also show a small (up to 10%) increase in metaprogram instantiation speed on some compilers when loop unrolling is used.

-
-
-
- -
-
-
-

3. Lambda facility

-
-
- -

The MPL's lambda facility allows the inline composition of class templates into “lambda expressions”, which are classes and can therefore be passed around as ordinary metafunction classes, or transformed into metafunction classes before application using the expression:

- -
-typedef mpl::lambda<expr>::type func;
-
- -

For example, boost::remove_const traits template from Boost type_traits library [TTL] is a class template (obviously), or a metafunction in MPL terminology. The simplest example of an “inline composition” of it would be something like:

- -
-typedef boost::remove_const<_1> expr;
-
- -

This forms a so called “lambda expression”, which is neither a metafunction class, nor a metafunction, yet can be passed around everywhere because it's an ordinary C++ class, because all MPL facilities are polymorphic with respect to their arguments. Now, that lambda expression can be transformed into a metafunction class using the MPL's lambda facility:

- -
-typedef boost::remove_const<_1> expr;
-typedef mpl::lambda<expr>::type func;
-
- -

The func is a unary metafunction class and can be used as such. In particular, it can be pass around or invoked (applied):

- -
-typedef mpl::apply<func,int const>::type res;
-BOOST_MPL_ASSERT_IS_SAME(res, int);
-
- -

or even

- -
-typedef func::apply<int const>::type res;
-BOOST_MPL_ASSERT_IS_SAME(res, int);
-
- -

Inline composition is very appealing syntactically when one deals with metafunctions, because it makes the expression obvious:

- -
-typedef mpl::logical_or<
-      mpl::less< mpl::size_of<_1>, mpl::int_c<16> >
-    , boost::is_same<_1,_2>
-    > expr;
-
-typedef mpl::lambda<expr>::type func;
-
- -

And one does not have to specify the last part (typedef lambda<expr>::type func), because all the algorithms do this to any of their metafunction class operands internally (a lambda<T>::type expression applied to a metafunction class gives back the same metafunction class, so it's safe to apply the expression unconditionally).

- -

The alternative way to write an equivalent of the above metafunction class would be:

- -
-typedef bind<
-      mpl::meta_fun2<mpl::logical_or>
-    , mpl::bind< mpl::meta_fun2<mpl::less>
-        , mpl::bind< mpl::meta_fun1<mpl::size_of>,_1 >
-        , mpl::int_c<16>
-        >
-    , mpl::bind< mpl::meta_fun2<boost::is_same>,_1,_2 >
-    > func;
-
- -

Or to use mpl::compose_ family of templates in a similar way. Here, we use mpl::meta_fun templates to convert metafunctions into metafunction classes and then combine them using mpl::bind. The transformation from this form to the above inline lambda expression and vice-versa is mechanical, and that is essentially what the typedef mpl::lambda<expr>::type expression does.

- -

For its own metafunctions (algorithms, primitives, etc.), MPL enables one to write the above in a less cumbersome way:

- -
-typedef mpl::bind<
-      mpl::logical_or<>
-    , mpl::bind< mpl::less<>, mpl::bind<mpl::size_of<>,_1>, mpl::int_c<16> >
-    , mpl::bind< mpl::make_f2<boost::is_same>, _1,_2 >
-    > func;
-
- -

Note that we still have to wrap is_same into make_f2, because it's a foreign template.

- -

Now, about combining class template metafunctions and metafunction classes in the single lambda expression - it can be done like this:

- -
-struct my_predicate
-{
-    template< typename T1, typename T2 > struct apply
-    {
-        //...
-    };
-};
-
-typedef mpl::logical_or<
-      mpl::less< mpl::size_of<_>,mpl::int_c<16> >
-    , mpl::bind< my_predicate,_,_ > // here
-    > expr;
-
- -

To bind something to one of its arguments (or change the order of parameters), then use either:

- -
-typedef mpl::logical_or<
-      mpl::less< mpl::size_of<_>,mpl::int_c<16> >
-    , mpl::bind<my_predicate,int,_>::type // here
-    > expr;
-
- -

or

- -
-typedef mpl::logical_or<
-      mpl::less< mpl::size_of<_>,mpl::int_c<16> >
-    , my_predicate::apply<int,_> // here
-    > expr;
-
-
- -
-
-
-

4. Code generation facilities

-
-
- -

There are cases, especially in the domain of numeric computation, when one wants to perform some part of the calculations at compile-time, and then pass the results to a run-time part of the program for further processing. For example, suppose one has implemented a complex compile-time algorithm that works with fixed-point arithmetic:

- -
-// fixed-point algorithm input
-typedef mpl::vector<
-      mpl::fixed_c<-1,2345678>
-    , mpl::fixed_c<9,0001>
-    // ..
-    , mpl::fixed_c<3,14159>
-    > input_data;
-
-/*
-  complex compile-time algorithm 
-*/
-typedef /*...*/ result_data;
-
- -

Suppose the result_data here is a sequence of mpl::fixed_c types that keeps the results of the algorithm, and now one wishes to feed that result to the run-time part of the algorithm. With MPL she can do this:

- -
-double my_algorithm()
-{
-    // passing the results to the run-time part of the program
-    std::vector<double> results;
-    results.reserve(mpl::size<result_data>::value);
-    mpl::for_each<numbers,_>(
-          boost::bind(&std::vector<double>::push_back, &results, _1)
-        );
-    // ...
-}
-
- -

The for_each<numbers,_>(...) call is what actually transfers the compile-time result_data into run-time results. for_each is a function template declared as:

- -
-template<
-      typename Seq
-    , typename TransformOp
-    , typename F
-    >
-void for_each(F f)
-{
-    // ...
-}
-
- -

To call the function, one is required to explicitly provide two actual template parameters, a compile-time sequence Seq and a unary transformation metafunction TransformOp, plus a run-time function argument f (in our example, numbers, _, and boost::bind(...) correspondingly). f is a function object which operator() is called for every element in the Seq tranfromed by TransformOp.

- -

Applying this to our example, the

- -
-mpl::for_each<numbers,_>(
-      boost::bind(&std::vector<double>::push_back, &results, _1)
-    );
-
- -

call is roughly equivalent to this:

- -
-f(mpl::apply< _,mpl::at_c<result_data,0>::type >::type());
-f(mpl::apply< _,mpl::at_c<result_data,1>::type >::type());
-// ...
-f(mpl::apply< _,mpl::at_c<result_data,n>::type >::type());
-
- -

where n == mpl::size<result_data>::type::value.

-
- -
-
-
-

5. Example: a compile-time FSM generator

-
-
- -

Finite state machines (FSMs) are an important tool for describing and implementing program behavior [HU79], [Mar98]. They also are a good example of a domain in which metaprogramming can be applied to reduce the amount of repetitive and boilerplate operations one must perform in order to implement these simple mathematical models in code. Below we present a simple state machine generator that has been implemented using Boost Metaprogramming Library facilities. The generator takes a compile-time automata description, and converts it into C++ code that implements the FSM at run-time.

- -

The FSM description is basically a combination of states and events plus a state transition table (STT), which ties them all together. The generator walks through the table and generates the state machine's process_event method that is the essence of an FSM.

- -

Suppose we want to implement a simple music player using a finite state machine model. The state transition table for the FSM is shown in Table 1. The STT format reflects the way one usually describes the behavior of an FSM in plain English. For example, the first line of the table can be read as follows: “If the model is in the stopped state and the play_event is received, then the do_play transition function is called, and the model transitions to the playing state”.

- -
- ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
StateEventNext stateTransition function
stoppedplay_eventplayingdo_play
playingstop_eventstoppeddo_stop
playingpause_eventpauseddo_pause
pausedplay_eventplayingdo_resume
pausedstop_eventstoppeddo_stop
- -

Table 1. Player's state transition table with actions

-
- -

The transition table provides us with a complete formal definition of the target FSM, and there are several ways to transform that definition into code. For instance, if we define states as members of an enumeration type, and events as classes derived from some base event class 10 , like so:

- -
-class player
-{
- public:
-    // event declarations
-    struct event;
-    struct play_event;
-    struct stop_event;
-    struct pause_event;
-
-    // "input" function
-    void process_event(event const&); // throws
-
- private:
-    // states
-    enum state_t { stopped, playing, paused };
-
-    // transition functions
-    void do_play(play_event const&);
-    void do_stop(stop_event const&);
-    void do_pause(pause_event const&);
-    void do_resume(play_event const&);
-
- private:
-    state_t m_state;
-};
-
- -

then the most straightforward way to derive the FSM implementation from the above table would be something like this:

- -
-void player::process_event(event const& e)
-{
-    if (m_state == stopped)
-    {
-        if (typeid(e) == typeid(play_event))
-        {
-            do_play(static_cast<play_event const&>(e));
-            m_state = playing;
-            return;
-        }
-    }
-    else if (m_state == playing)
-    {
-        if (typeid(e) == typeid(stop_event))
-        {
-            do_stop(static_cast<stop_event const&>(e));
-            m_state = stopped;
-            return;
-        }
-
-        if (typeid(e) == typeid(pause_event))
-        {
-            do_pause(static_cast<pause_event const&>(e));
-            m_state = paused;
-            return;
-        }
-    }
-    else if (m_state == paused)
-    {
-        if (typeid(e) == typeid(stop_event))
-        {
-            do_stop(static_cast<stop_event const&>(e));
-            m_state = stopped;
-            return;
-        }
-
-        if (typeid(e) == typeid(play_event))
-        {
-            do_play(static_cast<play_event const&>(e));
-            m_state = playing;
-            return;
-        }
-    }
-    else
-    {
-        throw logic_error(
-            boost::format("unknown state: %d")
-                % static_cast<int>(m_state)
-            );
-    }
-
-    throw std::logic_error(
-        "unexpected event: " + typeid(e).name()
-        );
-}
-
- -

Although there is nothing particularly wrong with implementing an FSM's structure using nested if (or switch-case) statements, the obvious weakness of this approach is that most of the above code is boilerplate. What one tends to do with boilerplate code is to copy and paste it, then change names etc. to adjust it to its new location; and that's where the errors are most likely to creep in. Since all the lines of event processing look alike (structurally), it's very easy to overlook or forget something that needs to be changed, and many such errors won't appear until the runtime.

- -

The transition table of our FSM is just five lines long; ideally, we would like the skeleton implementation of the automata's controlling logic to be equally short (or, at least, to look equally short, i.e. to be encapsulated in some form so we never worry about it).

- -
-
-
-

5.1. Implementation

-
-
- -

To represent the STT in a C++ program, we define a transition class template that represents a single line of the table. Then the table itself can be represented as a sequence of such lines:

- -
-typedef mpl::list<
-      transition<stopped, play_event,  playing, &player::do_play>
-    , transition<playing, stop_event,  stopped, &player::do_stop>
-    , transition<playing, pause_event, paused,  &player::do_pause>
-    , transition<paused,  play_event,  playing, &player::do_resume>
-    , transition<paused,  stop_event,  stopped, &player::do_stop>
-    >::type transition_table;
-
- -

Now, the complete FSM will look like this:

- -
-class player
-    : state_machine<player>
-{
- private:
-    typedef player self_t;
-
-    // state invariants
-    void stopped_state_invariant();
-    void playing_state_invariant();
-    void paused_state_invariant();
-
-    // states (invariants are passed as non-type template arguments,
-    // and are called then the FSM enters the corresponding state)
-    typedef state<0, &self_t::stopped_state_invariant> stopped;
-    typedef state<1, &self_t::playing_state_invariant> playing;
-    typedef state<2, &self_t::paused_state_invariant> paused;
-
- private:
-    // event declarations; events are represented as types, 
-    // and can carry a specific data for each event;
-    // but it's not needed for generator, so we define them later
-    struct play_event;
-    struct stop_event;
-    struct pause_event;
-
-    // transition functions
-    void do_play(play_event const&);
-    void do_stop(stop_event const&);
-    void do_pause(pause_event const&);
-    void do_resume(play_event const&);
-
-    // STT
-    friend class state_machine<player>;
-    typedef mpl::list<
-          transition<stopped, play_event,  playing, &player::do_play>
-        , transition<playing, stop_event,  stopped, &player::do_stop>
-        , transition<playing, pause_event, paused,  &player::do_pause>
-        , transition<paused,  play_event,  playing, &player::do_resume>
-        , transition<paused,  stop_event,  stopped, &player::do_stop>
-        >::type transition_table;
-};
-
- -

That's all - the above will generate a complete FSM implementation according to our specification. The only thing we need before using it is the definition of the event types (that were just forward declared before):

- -
-// event definitions
-struct player::play_event
-    : player::event
-{
-};
-
-// ...
-
- -

The usage is simple as well:

- -
-int main()
-{
-    // usage example
-    player p;
-    p.process_event(player::play_event());
-    p.process_event(player::pause_event());
-    p.process_event(player::play_event());
-    p.process_event(player::stop_event());
-    return 0;
-}
-
-
- -
-
-
-

5.2. Related work

-
-
- -

A notable prior work in the field of automation of general-purpose state machine implementation in C++ is the Robert Martin's State Machine Compiler [SMC]. The SMC takes an ASCII description of the machine's state transition table and produces C++ code that implements the FSM using a variation of State design pattern [Hun91], [GHJ+95]. Lafreniere [Laf00] presents another approach, where no external tools are used, and the FSMs are table driven.

-
-
- -
-
-
-

6. Acknowledgements

-
-
- -

Peter Dimov contributed the bind functionality without which compile-time lambda expressions wouldn't have been possible. The MPL implementation would have been much more difficult without Vesa Karvonen's wonderful Boost Preprocessor Metaprogramming Library. Authors are also greatly indebted to David B. Held who kindly volunteered to thoroughly edit this document. Of course, any remaining errors are exclusively ours.

-
- -
-
-
-

References

-
-
- -
-

[Abr01] David Abrahams and Carlos Pinto Coelho, Effects of Metaprogramming Style on Compilation Time, 2001

-
- -
-

[Ale01] Andrei Alexandrescu, Modern C++ Design: Generic Programming and Design Patterns Applied, Addison-Wesley, ISBN 0-201-70431-5, 2001

-
- -
-

[CE98] Krzysztof Czarnecki and Ulrich Eisenecker, Metalisp, http://home.t-online.de/home/Ulrich.Eisenecker/meta.htm

-
- -
-

[CE00] Krzysztof Czarnecki and Ulrich Eisenecker, Generative Programming: Methods, Tools, and Applications, Addison-Wesley, ISBN 0-201-30977-7, 2000

-
- -
-

[EBNF] ISO/IEC 14977:1996(E), Information technology — Syntactic metalanguage — Extended BNF, ISO/IEC, 1996

-
- -
-

[GHJ+95] Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides, Design Patterns, Elements of Reusable Object-Oriented Software, Addison-Wesley, ISBN 0-201-63361-2, 1995

-
- -
-

[HU79] Hopcroft and Ullman, Introduction to automata theory, languages and computations, Addison-Wesley, 1979

-
- -
-

[Hud89] Paul Hudak, Conception, Evolution, and Application of Functional Programming Languages, ACM Computing Surveys, Association for Computing Machinery (ACM), ISSN 0360-0300, Vol. 21, No. 3, pp. 359-411, September, 1989

-
- -
-

[Hun91] Immo Huneke, Finite State Machines: A Model of Behavior for C++, C++ Report, SIGS Publications Inc., ISSN 1040-6042, 1991

-
- -
-

[ISO98] ISO/IEC 14882:1998(E), Programming languages — C++, ISO/IEC, 1998

-
- -
-

[Joh79] Stephen C. Johnson, Yacc: Yet Another Compiler Compiler, UNIX Programmer's Manual, Vol. 2b, pp. 353-387, 1979

-
- -
-

[Laf00] David Lafreniere, State Machine Design in C++, C/C++ User Journal, CMP Media LCC, ISSN 1075-2838, Vol. 18, No. 5, May 1998

-
- -
-

[Loki] The Loki library, http://sourceforge.net/projects/loki-lib/

-
- -
-

[Mar98] Robert C. Martin, UML Tutorial: Finite State Machines, C++ Report, SIGS Publications Inc., ISSN 1040-6042, June 1998

-
- -
-

[MPLR] Boost MPL Library Reference Documentation, http://www.mywikinet.com/mpl/ref/Table_of_Content.html

-
- -
-

[PRE] Vesa Karvonen, Boost Preprocessor Metaprogramming library, http://www.boost.org/libs/preprocessor/doc/

-
- -
-

[SMC] Robert C. Martin, SMC - Finite State Machine Compiler (C++), http://www.objectmentor.com/resources/downloads/index

-
- -
-

[STL94] A. A. Stepanov and M. Lee, The Standard Template Library, Hewlett-Packard Laboratories, 1994

-
- -
-

[SPL] Boost Smart Pointer library, http://www.boost.org/libs/smart_ptr/

-
- -
-

[SS75] Gerald J. Sussman and Guy L. Steele Jr., Scheme: An interpreter for extended lambda calculus, MIT AI Memo 349, Massachusetts Institute of Technology, May 1975

-
- -
-

[TTL] Boost Type Traits library, http://www.boost.org/libs/type_traits/

-
- -
-

[Vel95a] Todd Veldhuizen, Using C++ template metaprograms, C++ Report, SIGS Publications Inc., ISSN 1040-6042, Vol. 7, No. 4, pp. 36-43, May 1995

-
- -
-

[Vel95b] Todd Veldhuizen, Expression templates, C++ Report, SIGS Publications Inc., ISSN 1040-6042, Vol. 7, No. 5, pp. 26-31, Jun 1995

-
- -
-

[Unr] Erwin Unruh, Prime number computation, ANSI X3J16-94-0075/ISO WG21-462

-
-
- -

-
-
-

1 Although it would be easy to implement pointed_type using partial specialization to distinguish the case where T is a pointer, if_ is likely to be the right tool for dealing with more complex conditionals. For the purposes of exposition, please suspend disbelief!

-
- -
-

2 In fact it's already broken: apply_twice doesn't even fit the metafunction concept since it requires a template (rather than a type) as its first parameter, which breaks the metafunction protocol.

-
- -
-

3 A more precise definition of these concepts can be found in the library reference documentation [MPLR].

-
- -
-

4 Random access is almost as important at compile-time as it is at run-time. For example, searching for an item in a sorted random-access sequence using lower_bound can be much faster than performing the same operation on a forward-access-only list.

-
- -
-

5 Here is another, even more elegant implementation:

- -
-template< typename Sequence >
-struct largest
-{
-    typedef typename mpl::max_element<
-          mpl::transform_view<
-              Sequence
-            , mpl::size_of<_>
-            >
-        >::type type;
-};
-
-
- -
-

6 Ideally, if going this route, all the templates should be re-implemented for every integral type - char, int, short, long, etc.

-
- -
-

7 The same technique was suggested by Czarnecki and Eisenecker in [CE00].

-
- -
-

8 It could be much more, depending on the complexity of the apply<...> expression, whose depth is added to the overall recursion depth.

-
- -
-

9 This implementation detail is made relatively painless through heavy reliance on the Boost Preprocessor Library, so only one copy of the code needs to be maintained.

-
- -
-

10 The events need to be passed to action functions, as they may contain some event-specific information for an action.

-
-
-
- - - diff --git a/doc/paper/src/abstract.sgml b/doc/paper/src/abstract.sgml deleted file mode 100644 index 3c6dc1d..0000000 --- a/doc/paper/src/abstract.sgml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - AlekseyGurtovoy - - MetaCommunications -
agurtovoy@meta-comm.com - - - - - DavidAbrahams - - Boost Consulting -
david.abrahams@rcn.com - - - - - - -This paper describes the &Boost; &Cxx; template metaprogramming library (&MPL;), an extensible compile-time framework of algorithms, sequences and metafunction classes. The library brings together important abstractions from the generic and functional programming worlds to build a powerful and easy-to-use toolset which makes template metaprogramming practical enough for the real-world environments. The &MPL; is heavily influenced by its run-time equivalent - the Standard Template Library (STL), a part of the C++ standard library , . Like the STL, it defines an open conceptual and implementation framework which can serve as a foundation for future contributions in the domain. The library's fundamental concepts and idioms enable the user to focus on solutions without navigating the universe of possible ad-hoc approaches to a given metaprogramming problem, even if no actual &MPL; code is used. The library also provides a compile-time lambda expression facility enabling arbitrary currying and composition of class templates, a feature whose runtime counterpart is often cited as missing from the STL. This paper explains the motivation, usage, design, and implementation of the &MPL; with examples of its real-life applications, and offers some lessons learned about &Cxx; template metaprogramming. - - - - -template metaprogramming -generic programming -programming languages -C++ -STL -type systems -polymorphism -compile-time - - - diff --git a/doc/paper/src/acknowl.sgml b/doc/paper/src/acknowl.sgml deleted file mode 100644 index f91ab72..0000000 --- a/doc/paper/src/acknowl.sgml +++ /dev/null @@ -1,10 +0,0 @@ - - -
-Acknowledgements</> - -<para> -Peter Dimov contributed the <literal>bind</> functionality without which compile-time lambda expressions wouldn't have been possible. The &MPL; implementation would have been much more difficult without Vesa Karvonen's wonderful Boost Preprocessor Metaprogramming Library. Authors are also greatly indebted to David B. Held who kindly volunteered to thoroughly edit this document. Of course, any remaining errors are exclusively ours. -</> - -</section> diff --git a/doc/paper/src/body.sgml b/doc/paper/src/body.sgml deleted file mode 100644 index bde300a..0000000 --- a/doc/paper/src/body.sgml +++ /dev/null @@ -1,41 +0,0 @@ -<!doctype article public "-//OASIS//DTD DocBook V4.1//EN" -[ -<!-- abbreviations --> -<!entity mdash "-"> -<!entity Boost "<literal>Boost</>"> -<!entity Cxx "C++"> -<!entity C "C"> -<!entity MPL "MPL"> -<!entity BMPL "Boost Metaprogramming Library"> -<!entity mdat "metadata"> -<!entity mping "metaprogramming"> -<!entity mfn "metafunction"> -<!entity unspec "/*unspecified*/"> - -<!-- physical entities --> -<!entity abstract SYSTEM "abstract.sgml"> -<!entity introduction SYSTEM "introduction.sgml"> -<!entity usage SYSTEM "usage.sgml"> -<!entity typeselection SYSTEM "typeselection.sgml"> -<!entity metafunctions SYSTEM "metafunctions.sgml"> -<!entity sequences SYSTEM "sequences.sgml"> -<!entity lambda SYSTEM "lambda.sgml"> -<!entity codegeneration SYSTEM "codegeneration.sgml"> -<!entity example SYSTEM "example.sgml"> -<!entity acknowl SYSTEM "acknowl.sgml"> -<!entity references SYSTEM "references.sgml"> -]> - -<article> -<title>The Boost &Cxx; Metaprogramming Library</> - -&abstract; -&introduction; -&usage; -λ -&codegeneration; -&example; -&acknowl; -&references; - -</article> diff --git a/doc/paper/src/codegeneration.sgml b/doc/paper/src/codegeneration.sgml deleted file mode 100644 index 6a9227c..0000000 --- a/doc/paper/src/codegeneration.sgml +++ /dev/null @@ -1,96 +0,0 @@ - -<!-- ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| section --> -<section id="codegeneration"> -<title>Code generation facilities</> - -<para> -There are cases, especially in the domain of numeric computation, when one wants to perform some part of the calculations at compile-time, and then pass the results to a run-time part of the program for further processing. For example, suppose one has implemented a complex compile-time algorithm that works with fixed-point arithmetic: -</> - -<programlisting> -<![CDATA[ -// fixed-point algorithm input -typedef mpl::vector< - mpl::fixed_c<-1,2345678> - , mpl::fixed_c<9,0001> - // .. - , mpl::fixed_c<3,14159> - > input_data; - -/* - complex compile-time algorithm -*/ -typedef /*...*/ result_data; -]]> -</> - -<para> -Suppose the <literal>result_data</> here is a sequence of <literal>mpl::fixed_c</> types that keeps the results of the algorithm, and now one wishes to feed that result to the run-time part of the algorithm. With &MPL; she can do this: -</> - -<programlisting> -<![CDATA[ -double my_algorithm() -{ - // passing the results to the run-time part of the program - std::vector<double> results; - results.reserve(mpl::size<result_data>::value); - mpl::for_each<numbers,_>( - boost::bind(&std::vector<double>::push_back, &results, _1) - ); - // ... -} -]]> -</> - -<para> -The <literal>for_each<numbers,_>(...)</> call is what actually transfers the compile-time <literal>result_data</> into run-time <literal>results</>. <literal>for_each</> is a function template declared as: -</> - -<programlisting> -<![CDATA[ -template< - typename Seq - , typename TransformOp - , typename F - > -void for_each(F f) -{ - // ... -} -]]> -</> - -<para>To call the function, one is required to explicitly provide two actual template parameters, a compile-time sequence <literal>Seq</> and a unary transformation metafunction <literal>TransformOp</>, plus a run-time function argument <literal>f</> (in our example, <literal>numbers</>, <literal>_</>, and <literal>boost::bind(...)</> correspondingly). <literal>f</> is a function object which <literal>operator()</> is called for every element in the <literal>Seq</> tranfromed by <literal>TransformOp</>. -</> - -<para> -Applying this to our example, the -</> - -<programlisting> -<![CDATA[ -mpl::for_each<numbers,_>( - boost::bind(&std::vector<double>::push_back, &results, _1) - ); -]]> -</> - -<para> -call is roughly equivalent to this: -</> - -<programlisting> -<![CDATA[ -f(mpl::apply< _,mpl::at_c<result_data,0>::type >::type()); -f(mpl::apply< _,mpl::at_c<result_data,1>::type >::type()); -// ... -f(mpl::apply< _,mpl::at_c<result_data,n>::type >::type()); -]]> -</> - -<para> -where <literal>n == mpl::size<result_data>::type::value</>. -</> - -</section> diff --git a/doc/paper/src/example.sgml b/doc/paper/src/example.sgml deleted file mode 100644 index 868a06f..0000000 --- a/doc/paper/src/example.sgml +++ /dev/null @@ -1,294 +0,0 @@ - -<!-- ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| section --> -<section id="example"> -<title>Example: a compile-time FSM generator</> - -<para> -Finite state machines (<acronym>FSMs</>) are an important tool for describing and implementing program behavior <citation><xref linkend="ref.hu79"></>, <citation><xref linkend="ref.mar98"></>. They also are a good example of a domain in which &mping; can be applied to reduce the amount of repetitive and boilerplate operations one must perform in order to implement these simple mathematical models in code. Below we present a simple state machine generator that has been implemented using &BMPL; facilities. The generator takes a compile-time automata description, and converts it into &Cxx; code that implements the FSM at run-time. -</> - -<para> -The FSM description is basically a combination of states and events plus a state transition table (<acronym>STT</>), which ties them all together. The generator walks through the table and generates the state machine's <literal>process_event</> method that is the essence of an FSM. -</> - -<para> -Suppose we want to implement a simple music player using a finite state machine model. The state transition table -for the FSM is shown in <xref linkend="example.fsm.stt">. The STT format reflects the way one usually describes the behavior of an FSM in plain English. For example, the first line of the table can be read as follows: <quote>If the model is in the <literal>stopped</> state and the <literal>play_event</> is received, then the <literal>do_play</> transition function is called, and the model transitions to the <literal>playing</> state</>. -</> - -<table id="example.fsm.stt" frame="none"> -<title>Player's state transition table with actions</> - -<tgroup cols="4" align="left"> -<thead> -<row> - <entry>State</> - <entry>Event</> - <entry>Next state</> - <entry>Transition function</> -</> -</> - -<tbody> -<row> - <entry><literal>stopped</></> - <entry><literal>play_event</></> - <entry><literal>playing</></> - <entry><literal>do_play</></> -</> -<row> - <entry><literal>playing</></> - <entry><literal>stop_event</></> - <entry><literal>stopped</></> - <entry><literal>do_stop</></> -</> -<row> - <entry><literal>playing</></> - <entry><literal>pause_event</></> - <entry><literal>paused</></> - <entry><literal>do_pause</></> -</> -<row> - <entry><literal>paused</></> - <entry><literal>play_event</></> - <entry><literal>playing</></> - <entry><literal>do_resume</></> -</> -<row> - <entry><literal>paused</></> - <entry><literal>stop_event</></> - <entry><literal>stopped</></> - <entry><literal>do_stop</></> -</> -</> -</tgroup> - -</table> - -<para> -The transition table provides us with a complete formal definition of the target FSM, and there are several ways to -transform that definition into code. For instance, if we define states as members of an enumeration type, and events as classes derived from some base <literal>event</> class - -<footnote id="note.fsm"><para>The events need to be passed to action functions, as they may contain some event-specific information for an action.</></> - -, like so: -</> - -<programlisting> -<![CDATA[ -class player -{ - public: - // event declarations - struct event; - struct play_event; - struct stop_event; - struct pause_event; - - // "input" function - void process_event(event const&); // throws - - private: - // states - enum state_t { stopped, playing, paused }; - - // transition functions - void do_play(play_event const&); - void do_stop(stop_event const&); - void do_pause(pause_event const&); - void do_resume(play_event const&); - - private: - state_t m_state; -}; -]]> -</> - -<para> -then the most straightforward way to derive the FSM implementation from the above table would be something -like this: -</> - -<programlisting> -<![CDATA[ -void player::process_event(event const& e) -{ - if (m_state == stopped) - { - if (typeid(e) == typeid(play_event)) - { - do_play(static_cast<play_event const&>(e)); - m_state = playing; - return; - } - } - else if (m_state == playing) - { - if (typeid(e) == typeid(stop_event)) - { - do_stop(static_cast<stop_event const&>(e)); - m_state = stopped; - return; - } - - if (typeid(e) == typeid(pause_event)) - { - do_pause(static_cast<pause_event const&>(e)); - m_state = paused; - return; - } - } - else if (m_state == paused) - { - if (typeid(e) == typeid(stop_event)) - { - do_stop(static_cast<stop_event const&>(e)); - m_state = stopped; - return; - } - - if (typeid(e) == typeid(play_event)) - { - do_play(static_cast<play_event const&>(e)); - m_state = playing; - return; - } - } - else - { - throw logic_error( - boost::format("unknown state: %d") - % static_cast<int>(m_state) - ); - } - - throw std::logic_error( - "unexpected event: " + typeid(e).name() - ); -} -]]> -</> - -<para> -Although there is nothing particularly wrong with implementing an FSM's structure using nested <literal>if</> (or <literal>switch-case</>) statements, the obvious weakness of this approach is that most of the above code is boilerplate. What one tends to do with boilerplate code is to copy and paste it, then change names etc. to adjust it to its new location; and that's where the errors are most likely to creep in. Since all the lines of event processing look alike (structurally), it's very easy to overlook or forget something that needs to be changed, and many such errors won't appear until the runtime. -</> - -<para> -The transition table of our FSM is just five lines long; ideally, we would like the skeleton implementation of the automata's controlling logic to be equally short (or, at least, to look equally short, i.e. to be encapsulated in some form so we never worry about it). -</> - -<!-- ||||||||||||||||||||||||||||| subsection --> -<section id="example.impl"> -<title>Implementation</> - -<para> -To represent the STT in a &Cxx; program, we define a <literal>transition</> class template that represents a single line of the table. Then the table itself can be represented as a sequence of such lines: -</> - -<programlisting> -<![CDATA[ -typedef mpl::list< - transition<stopped, play_event, playing, &player::do_play> - , transition<playing, stop_event, stopped, &player::do_stop> - , transition<playing, pause_event, paused, &player::do_pause> - , transition<paused, play_event, playing, &player::do_resume> - , transition<paused, stop_event, stopped, &player::do_stop> - >::type transition_table; -]]></> - -<para> -Now, the complete FSM will look like this: -</> - -<programlisting> -<![CDATA[ -class player - : state_machine<player> -{ - private: - typedef player self_t; - - // state invariants - void stopped_state_invariant(); - void playing_state_invariant(); - void paused_state_invariant(); - - // states (invariants are passed as non-type template arguments, - // and are called then the FSM enters the corresponding state) - typedef state<0, &self_t::stopped_state_invariant> stopped; - typedef state<1, &self_t::playing_state_invariant> playing; - typedef state<2, &self_t::paused_state_invariant> paused; - - private: - // event declarations; events are represented as types, - // and can carry a specific data for each event; - // but it's not needed for generator, so we define them later - struct play_event; - struct stop_event; - struct pause_event; - - // transition functions - void do_play(play_event const&); - void do_stop(stop_event const&); - void do_pause(pause_event const&); - void do_resume(play_event const&); - - // STT - friend class state_machine<player>; - typedef mpl::list< - transition<stopped, play_event, playing, &player::do_play> - , transition<playing, stop_event, stopped, &player::do_stop> - , transition<playing, pause_event, paused, &player::do_pause> - , transition<paused, play_event, playing, &player::do_resume> - , transition<paused, stop_event, stopped, &player::do_stop> - >::type transition_table; -}; -]]> -</> - -<para> -That's all — the above will generate a complete FSM implementation according to our specification. The only thing we need before using it is the definition of the event types (that were just forward declared before): -</> - -<programlisting> -<![CDATA[ -// event definitions -struct player::play_event - : player::event -{ -}; - -// ... -]]> -</> - -<para> -The usage is simple as well: -</> - -<programlisting> -<![CDATA[ -int main() -{ - // usage example - player p; - p.process_event(player::play_event()); - p.process_event(player::pause_event()); - p.process_event(player::play_event()); - p.process_event(player::stop_event()); - return 0; -} -]]> -</> -</section> - -<!-- ||||||||||||||||||||||||||||| subsection --> -<section id="example.relatedwork"> -<title>Related work</> - -<para> -A notable prior work in the field of automation of general-purpose state machine implementation in &Cxx; is the Robert Martin's <emphasis>State Machine Compiler</> <citation><xref linkend="ref.smc"></>. The SMC takes an ASCII description of the machine's state transition table and produces &Cxx; code that implements the FSM using a variation of State design pattern <citation><xref linkend="ref.hun91"></>, <citation><xref linkend="ref.ghj95"></>. Lafreniere <citation><xref linkend="ref.laf00"></> presents another approach, where no external tools are used, and the FSMs are table driven. -</> -</section> - -</section> diff --git a/doc/paper/src/introduction.sgml b/doc/paper/src/introduction.sgml deleted file mode 100644 index 1dbfa81..0000000 --- a/doc/paper/src/introduction.sgml +++ /dev/null @@ -1,375 +0,0 @@ -<section id="intro"> -<title>Introduction</> - -<para> -Metaprogramming is usually defined as the creation of programs which generate other programs. Parser generators such as YACC <citation><xref linkend="ref.Joh79"></> are examples of one kind of program-generating program. The input language to YACC is a context-free grammar in Extended Backus-Naur Form <citation><xref linkend="ref.EBNF"></>, and its output is a program which parses that grammar. Note that in this case the metaprogram (YACC) is written in a language (&C;) which does not directly support the description of generated programs. These specifications, which we'll call <emphasis>&mdat;</>, are not written in &C;, but in a <emphasis>meta-language</>. Because the the rest of the user's program typically requires a general-purpose programming system and must interact with the generated parser, the &mdat; is translated into &C;, which is then compiled and linked together with the rest of the system. The &mdat; thus undergoes two translation steps, and the user is always very conscious of the boundary between her &mdat; and the rest of her program. -</> - -<!-- ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| section --> -<section id="intro.native"> -<title>Native language metaprogramming</> - -<para> -A more interesting form of &mping; is available in languages such as Scheme <citation><xref linkend="ref.SS75"></>, where the generated program specification is given in the same language as the metaprogram itself. The metaprogrammer defines her meta-language as a subset of the expressible forms of the underlying language, and program generation can take place in the same translation step used to process the rest of the user's program. This -allows users to switch transparently between ordinary programming, generated program specification, and &mping;, often without being aware of the transition. -</> -</section> - -<!-- ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| section --> -<section id="intro.cxx"> -<title>Metaprogramming in &Cxx;</> - -<para> -In &Cxx;, it was discovered almost by accident <citation><xref linkend="ref.Unr"></>, <citation><xref linkend="ref.Vel95a"></> that the template mechanism provides a rich facility for computation at compile-time. In this section, we'll explore the basic mechanisms and some common idioms used for metaprogramming in &Cxx;. -</> - -<!-- ||||||||||||||||||||||||||||| subsection --> -<section id="intro.cxx.numeric"> -<title>Numeric computations</> - -<para> -The availability of <emphasis>non-type template parameters</> makes it possible to perform integer computations at compile-time. For example, the following template computes the factorial of its argument: -</> - -<programlisting> -<![CDATA[ -template< unsigned n > -struct factorial -{ - static const unsigned value = n * factorial<n-1>::value; -}; - -template<> -struct factorial<0> -{ - static const unsigned value = 1; -}; -]]> -</> - -<para> -The program fragment above is called a <emphasis>&mfn;</>, and it is easy to see its relationship to a function designed to be evaluated at runtime: the <quote>&mfn; argument</> is passed as a template parameter, and its <quote>return value</> is defined as a nested static constant. Because of the hard line between the expression of compile-time and runtime computation in &Cxx;, metaprograms look different from their runtime counterparts. Thus, although as in Scheme the &Cxx; metaprogrammer writes her code in the same language as the ordinary program, only a subset -of the full &Cxx; language is available to her: those expressions which can be evaluated at compile-time. Compare the above with a straightforward runtime definition of the factorial function: -</> - -<programlisting> -unsigned factorial(unsigned N) -{ - return N == 0 ? 1 : N * factorial(N - 1); -} -</> - -<para> -While it is easy to see the analogy between the two recursive definitions, recursion is in general more important to &Cxx; metaprograms than it is to runtime &Cxx;. In contrast to languages such as Lisp where recursion is idiomatic, &Cxx; programmers will typically avoid recursion when possible. This is done not only for efficiency reasons, but also because of <quote>cultural momentum</>: recursive programs are simply harder (for &Cxx; programmers) to think about. Like pure Lisp, though, the &Cxx; template mechanism is a <emphasis>functional</> programming language: as such it rules out the use of data mutation required to maintain loop variables. -</> - -<para> -A key difference between the runtime and compile-time factorial functions is the expression of the termination condition: our meta-factorial uses template specialization as a kind of <emphasis>pattern-matching</> mechanism to describe the behavior when <literal>N</> is zero. The syntactic analogue in the runtime world would require two separate definitions of the same function. In this case the impact of the second definition is minimal, but in large -metaprograms the cost of maintaining and understanding the terminating definitions can become significant. -</> - -<para> -Note also that a &Cxx; &mfn;'s return value must be <emphasis>named</>. The name chosen here, <literal>value</>, is the same one used for all numeric returns in the &MPL;. As we'll see, establishing a consistent naming -convention for &mfn; returns is crucial to the power of the library. -</> -</section> - -<!-- ||||||||||||||||||||||||||||| subsection --> -<section id="intro.cxx.type"> -<title>Type computations</> - -<para> -How could we apply our <literal>factorial</> &mfn;? We might, for example, produce an array type of an appropriate size to hold all permutations of instances of another type: -</> - -<programlisting> -<![CDATA[ -// permutation_holder<T>::type is an array type which can contain -// all permutations of a given T. - -// unspecialized template for scalars -template< typename T > -struct permutation_holder -{ - typedef T type[1][1]; -}; - -// specialization for array types -template< typename T, unsigned N > -struct permutation_holder<T[N]> -{ - typedef T type[factorial<N>::value][N]; -}; -]]> -</> - -<para> -Here we have introduced the notion of a <emphasis>type computation</>. Like <literal>factorial</> above, <literal>permutation_holder</> template is a &mfn;. However, where <literal>factorial</> manipulates unsigned integer values, <literal>permutation_holder</> accepts and <quote>returns</> a type (as the nested typedef <literal>type</>). Because the &Cxx; type system provides a much richer set of expressions than anything we can use as a nontype template argument (e.g. the integers), &Cxx; metaprograms tend to be composed mostly of type computations. -</> -</section> - -<!-- ||||||||||||||||||||||||||||| subsection --> -<section id="intro.cxx.seq"> -<title>Type sequences</> - -<para> -The ability to programmatically manipulate collections of types is a central tool of most interesting &Cxx; metaprograms. Because this capability is so well-supported by the &MPL;, we'll provide just a brief -introduction to the basics here. Later on, we'll revisit the example below to show how it can be implemented using &MPL;. -</> - -<para> -First, we'd need a way to represent the collection. One idea might be to store the types in a structure: -</> - -<programlisting> -<![CDATA[ -struct types -{ - int t1; - long t2; - std::vector<double> t3; -}; -]]> -</> - -<para> -Unfortunately, this arrangement is not susceptible to the compile-time type introspection power that &Cxx; gives us: there's no way to find out what the names of the members are, and even if we assume that they're named according to some convention as above, there's no way to know how many members there are. The key to solving this problem is to -increase the uniformity of the representation. If we have a consistent way to get the first type of any sequence and the rest of the sequence, we can easily access all members: -</> - -<programlisting> -<![CDATA[ -template< typename First, typename Rest > -struct cons -{ - typedef First first; - typedef Rest rest; -}; - -struct nil {}; - -typedef - cons<int - , cons<long - , cons<std::vector<double> - , nil - > > > my_types; -]]> -</> - -<para> -The structure described by <literal>types</> above is the compile-time analogue of a singly-linked list; it has been first introduced by Czarnecki and Eisenecker in <citation><xref linkend="ref.ce98"></>. Now that we've adjusted the structure so that the &Cxx; template machinery can <quote>peel it apart</>, let's examine a simple metafunction which does so. Suppose a user wished to find the largest of an arbitrary collection of types. We can apply the recursive &mfn; formula which should by now be familiar: -</> - -<example id="example.largest"> -<title>'largest' metafunction</> -<programlisting> -<![CDATA[ -// choose the larger of two types -template< - typename T1 - , typename T2 - , bool choose1 = (sizeof(T1) > sizeof(T2)) // hands off! - > -struct choose_larger -{ - typedef T1 type; -}; - -// specialization for the case where sizeof(T2) >= sizeof(T1) -template< typename T1, typename T2 > -struct choose_larger< T1,T2,false > -{ - typedef T2 type; -}; - -// get the largest of a cons-list -template< typename T > struct largest; - -// specialization to peel apart the cons list -template< typename First, typename Rest > -struct largest< cons<First,Rest> > - : choose_larger< First, typename largest<Rest>::type > -{ - // type inherited from base -}; - -// specialization for loop termination -template< typename First > -struct largest< cons<First,nil> > -{ - typedef First type; -}; - -int main() -{ - // print the name of the largest of my_types - std::cout - << typeid(largest<my_types>::type).name() - << std::endl - ; -} -]]> -</> -</> - -<para> -There are several things worth noticing about this code: -</> - -<itemizedlist mark="box"> - -<listitem><para> -It uses a few ad-hoc, esoteric techniques, or <quote>hacks</>. The default template argument <literal>choose1</> (labeled <quote>hands off!</>) is one example. Without it, we would have needed yet another template to provide the implementation of <literal>choose_larger</>, or we would have had to provide the computation explicitly as a parameter to the template - perhaps not bad for this example, but it would make <literal>choose_larger</> much less useful and more error-prone. The other hack is the derivation of a specialization of <literal>largest</> from <literal>choose_larger</>. This is a code-saving device which allows the programmer to avoid writing <quote><literal>typedef - typename </>...<literal>::type type</></> in the template body. -</></> - -<listitem><para> -Even this simple metaprogram uses three separate partial specializations. The <literal>largest</> &mfn; uses <emphasis>two</> specializations. One might expect that this indicates there are two termination conditions, but there are not: one specialization is needed simply to deal with access to the sequence elements. These specializations make the code difficult to read by spreading the definition of a single &mfn; over several &Cxx; template definitions. Also, because they are <emphasis>partial</> specializations, they make the code unusable for a large community of &Cxx; programmers whose compilers don't support that feature. -</></> - -</itemizedlist> - -<para> -While these techniques are, of course, a valuable part of the arsenal of any good &Cxx; metaprogrammer, their use tends to make programs written in what is already an unusual style harder-to-read and harder-to-write. By encapsulating commonly-used structures and dealing with loop terminations internally, the &MPL; reduces the need for both tricky hacks and for template specializations. -</> -</section> - -</section> - -<!-- ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| section --> -<section id="intro.whymetaprog"> -<title>Why metaprogramming?</> - -<!-- -maybe we don't need another example of a metaprogram given what -we've done above? We could rewrite and cut most of this section... ---> - -<para> -It's worth asking why anyone would want to do this. After all, even a simple toy example like the factorial &mfn; is somewhat esoteric. To show how the type computation can be put to work, let's examine a simple example. The following code produces an array containing all possible permutations of another array: -</> - -<programlisting> -<![CDATA[ -// can't return an array in C++, so we need this wrapper -template< typename T > -struct wrapper -{ - T x; -}; - -// return an array of the N! permutations of 'in' -template< typename T > -wrapper< typename permutation_holder<T>::type > -all_permutations(T const& in) -{ - wrapper<typename permutation_holder<T>::type> result; - - // copy the unpermutated array to the first result element - unsigned const N = sizeof(T) / sizeof(**result.x); - std::copy(&*in, &*in + N, result.x[0]); - - // enumerate the permutations - unsigned const result_size = sizeof(result.x) / sizeof(T); - for (T* dst = result.x + 1; dst != result.x + result_size; ++dst) - { - T* src = dst - 1; - std::copy(*src, *src + N, *dst); - std::next_permutation(*dst, *dst + N); - } - return result; -} -]]> -</> - -<!-- ...up to this point --> - -<para> -The runtime definition of <literal>factorial</> would be useless in <literal>all_permutations</> above, since in &Cxx; the sizes of array members must be computed at compile-time. However, there are alternative approaches; how could we avoid &mping;, and what would the consequences be? -</> - -<orderedlist> - -<listitem> -<para> -We could write programs to interpret the &mdat; directly. In our factorial example, the array size could have been a runtime quantity; then we'd have been able to use the straightforward factorial function. However, that would imply the use of dynamic allocation, which is often expensive. -</> -<para> -To carry this further, YACC might be rewritten to accept a pointer-to-function returning tokens from the stream to be parsed, and a string containing the grammar description. This approach, however, would impose unacceptable runtime costs for most applications: either the parser would have to treat the grammar nondeterministically, exploring the grammar for each parse, or it would have to begin by replicating at runtime the substantial table-generation and optimization work of the existing YACC for each input grammar. -</> -</> - -<listitem> -<para> -We could replace the compile-time computation with our own analysis. After all, the size of arrays passed to - <literal>all_permutations</> are always known at compile-time, and thus can be known to its user. We could ask the user to supply the result type explicitly: -</> - -<programlisting> -<![CDATA[ -template< typename Result, typename T > -Result all_permutations(T const& input); -]]> -</> - -<para> -The costs to this approach are obvious: we give up expressivity (by requiring the user to explicitly specify implementation details), and correctness (by allowing the user to specify them incorrectly). Anyone who has had to write parser tables by hand will tell you that the impracticality of this approach is the very reason of YACC's existence. -</> -<para> -In a language such as &Cxx;, where the &mdat; can be expressed in the same language as the rest of the user's program, expressivity is further enhanced: the user can invoke metaprograms directly, without learning a foreign syntax or interrupting the flow of her code. -</> -</> - -</orderedlist> - -<para> -So, the motivation for &mping; comes down to the combination of three factors: efficiency, expressivity, and correctness. While in classical programming there is always a tension between expressivity and correctness on one hand and efficiency on the other, in the &mping; world we wield new power: we can move the computation required for -expressivity from runtime to compile-time. -</> -</section> - -<!-- ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| section --> -<section id="intro.whylibrary"> -<title>Why a metaprogramming <emphasis>library</>?</> - -<para> -One might just as well ask why we need any generic library: -</> - -<itemizedlist mark="box"> - -<listitem> -<para> -Quality. Code that is appropriate for a general-purpose library is usually incidental to the purpose of its users. To a library developer, it is the central mission. On average, the containers and algorithms provided by any given &Cxx; standard library implementation are more-flexible and better-implemented than the project-specific implementations which abound, because library development was treated as an end in itself rather than a task incidental to the development of some other application. With a centralized implementation for any given function, optimizations and improvements are more likely to have been applied. -</> -</> - -<listitem> -<para> -Re-use. More important even than the re-use of code which all libraries provide, a well-designed generic library establishes a <emphasis>framework of concepts and idioms</> which establishes a reusable mental model for approaching problems. Just as the &Cxx; Standard Template Library gave us iterator concepts and a function object protocol, the &BMPL; provides type-iterators and metafunction class protocol. A well-considered framework of idioms saves the metaprogrammer from considering irrelevant implementation details and allows her to concentrate on the problem at hand. -</> -</> - -<listitem> -<para> -Portability. A good library can smooth over the ugly realities of platform differences. While in theory a &mping; library is fully generic and shouldn't be concerned with these issues, in practice support for templates remains inconsistent even four years after standardization. This should perhaps not be surprising: &Cxx; templates are the language's furthest-reaching and most complicated feature, which largely accounts for the power of &mping; in &Cxx;. -</> -</> - -<listitem> -<para> -Fun. Repeating the same idioms over and over is <emphasis>tedious</>. It makes programmers tired and reduces productivity. Furthermore, when programmers get bored they get sloppy, and buggy code is even more costly than slowly-written code. Often the most useful libraries are simply patterns that have been <quote>plucked</> by an astute programmer from a sea of repetition. The &MPL; helps to reduce boredom by eliminating the need for the most commonly-repeated boilerplate coding patterns. -</> -</> - -</itemizedlist> - -<para> -As one can see, the &MPL;'s development is motivated primarily by the same practical, real-world considerations that justify the development of any other library. Perhaps this is an indication that template &mping; is finally ready to leave the realm of the esoteric and enter the lingua franca of every day programmers. -</> - -<!-- probably this paragraph would be better in the conclusions --> -</section> - -</section> diff --git a/doc/paper/src/lambda.sgml b/doc/paper/src/lambda.sgml deleted file mode 100644 index 74765cd..0000000 --- a/doc/paper/src/lambda.sgml +++ /dev/null @@ -1,142 +0,0 @@ - -<!-- ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| section --> -<section id="lambda"> -<title>Lambda facility</> - -<para> -The &MPL;'s lambda facility allows the <firstterm>inline composition</> of class templates into <quote>lambda expressions</>, which are classes and can therefore be passed around as ordinary metafunction classes, or transformed into metafunction classes before application using the expression: -</> - -<programlisting><![CDATA[ -typedef mpl::lambda<expr>::type func; -]]></> - -<para> -For example, <literal>boost::remove_const</> traits template from Boost <literal>type_traits</> library <citation><xref linkend="ref.TTL"></> is a class template (obviously), or a <link linkend="metafunctions">metafunction</> in &MPL; terminology. The simplest example of an <quote>inline composition</> of it would be something like: -</> - -<programlisting><![CDATA[ -typedef boost::remove_const<_1> expr; -]]></> - -<para> -This forms a so called <quote>lambda expression</>, which is neither a metafunction class, nor a metafunction, yet can be passed around everywhere because it's an ordinary &Cxx; class, because all &MPL; facilities are polymorphic with respect to their arguments. Now, that lambda expression can be <emphasis>transformed</> into a metafunction class using the &MPL;'s <literal>lambda</> facility: -</> - -<programlisting><![CDATA[ -typedef boost::remove_const<_1> expr; -typedef mpl::lambda<expr>::type func; -]]></> - -<para> -The <literal>func</> is a unary metafunction class and can be used as such. In particular, it can be pass around or invoked (applied): -</> - -<programlisting><![CDATA[ -typedef mpl::apply<func,int const>::type res; -BOOST_MPL_ASSERT_IS_SAME(res, int); -]]></> - -<para> -or even -</> - -<programlisting><![CDATA[ -typedef func::apply<int const>::type res; -BOOST_MPL_ASSERT_IS_SAME(res, int); -]]></> - -<para> -Inline composition is very appealing syntactically when one deals with metafunctions, because it makes the expression obvious: -</> - -<programlisting><![CDATA[ -typedef mpl::logical_or< - mpl::less< mpl::sizeof_<_1>, mpl::int_c<16> > - , boost::is_same<_1,_2> - > expr; - -typedef mpl::lambda<expr>::type func; -]]></> - -<para> -And one does not have to specify the last part (<literal>typedef lambda<expr>::type func</>), because all the algorithms do this to any of their metafunction class operands internally (a <literal>lambda<T>::type</> expression applied to a metafunction class gives back the same metafunction class, so it's safe to apply the expression unconditionally). -</> - -<para> -The alternative way to write an equivalent of the above metafunction class would be: -</> - -<programlisting><![CDATA[ -typedef bind< - mpl::meta_fun2<mpl::logical_or> - , mpl::bind< mpl::meta_fun2<mpl::less> - , mpl::bind< mpl::meta_fun1<mpl::sizeof_>,_1 > - , mpl::int_c<16> - > - , mpl::bind< mpl::meta_fun2<boost::is_same>,_1,_2 > - > func; -]]></> - -<para> -Or to use <literal>mpl::compose_</> family of templates in a similar way. Here, we use <literal>mpl::meta_fun</> templates to convert metafunctions into metafunction classes and then combine them using <literal>mpl::bind</>. The transformation from this form to the above inline lambda expression and vice-versa is mechanical, and that is essentially what the <literal>typedef mpl::lambda<expr>::type</> expression does. -</> - -<para> -For its own metafunctions (algorithms, primitives, etc.), &MPL; enables one to write the above in a less cumbersome way: -</> - -<programlisting><![CDATA[ -typedef mpl::bind< - mpl::logical_or<> - , mpl::bind< mpl::less<>, mpl::bind<mpl::sizeof_<>,_1>, mpl::int_c<16> > - , mpl::bind< mpl::make_f2<boost::is_same>, _1,_2 > - > func; -]]></> - -<para> -Note that we still have to wrap <literal>is_same</> into <literal>make_f2</>, because it's a foreign template. -</> - -<para> -Now, about combining class template metafunctions and metafunction classes in the single lambda expression - it can be done like this: -</> - -<programlisting><![CDATA[ -struct my_predicate -{ - template< typename T1, typename T2 > struct apply - { - //... - }; -}; - -typedef mpl::logical_or< - mpl::less< mpl::sizeof_<_>,mpl::int_c<16> > - , mpl::bind< my_predicate,_,_ > // here - > expr; -]]></> - -<para> -To bind something to one of its arguments (or change the order of parameters), then use either: -</> - -<programlisting><![CDATA[ -typedef mpl::logical_or< - mpl::less< mpl::sizeof_<_>,mpl::int_c<16> > - , mpl::bind<my_predicate,int,_>::type // here - > expr; -]]></> - -<para> -or -</> - -<programlisting><![CDATA[ -typedef mpl::logical_or< - mpl::less< mpl::sizeof_<_>,mpl::int_c<16> > - , my_predicate::apply<int,_> // here - > expr; -]]></> - -</section> diff --git a/doc/paper/src/metafunctions.sgml b/doc/paper/src/metafunctions.sgml deleted file mode 100644 index 4136b27..0000000 --- a/doc/paper/src/metafunctions.sgml +++ /dev/null @@ -1,282 +0,0 @@ - -<!-- ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| section --> -<section id="metafunctions"> -<title>Metafunctions</> - -<!-- ||||||||||||||||||||||||||||| subsection --> -<section id="metafunctions.simple"> -<title>The simple form</> - -<para> -In C++, the basic underlying language construct which allows parameterized compile-time computation is the <firstterm>class template</> (<citation><xref linkend="ref.ISO98"></>, section 14.5.1 [temp.class]). A bare class template is the simplest possible model we could choose for metafunctions: it can take types and/or non-type arguments as actual template parameters, and instantiation <quote>returns</> a new type. For example, the following produces a type derived from its arguments: -</> - -<programlisting> -<![CDATA[ -template< typename T1, typename T2 > -struct derive : T1, T2 -{ -}; -]]> -</> - -<para> -However, this model is far too limiting: it restricts the metafunction result not only to class types, but to instantiations of a given class template, to say nothing of the fact that every metafunction invocation introduces an additional level of template nesting. While that might be acceptable for this particular metafunction, any model which prevented us from <quote>returning</>, say, <literal>int</> is obviously not general enough. To meet this basic requirement, we must rely on a nested type to provide our return value: -</> - -<programlisting> -<![CDATA[ -template< typename T1, typename T2 > -struct derive -{ - struct type : T1, T2 {}; -}; - -// silly specialization, but demonstrates "returning" int -template<> -struct derive<void,void> -{ - typedef int type; -}; -]]> -</> - -<para> -Veldhuizen <citation><xref linkend="ref.Vel95a"></> was first to talk about class templates of this form as <quote>compile-time functions</>, and Czarnecki and Eisenecker <citation><xref linkend="ref.CE00"></> have introduced <quote>template metafunction</> as an equivalent term (they also use the simpler term <quote>metafunction</>, as do we). Czarnecki and Eisenecker have also recognized the limitations of the simple metafunction representation and suggested the form that we discuss in <xref linkend="metafunctions.classes">. -</> -</section> - -<!-- ||||||||||||||||||||||||||||| subsection --> -<section id="metafunctions.higherorder"> -<title>Higher-order metafunctions</> - -<para> -While syntactically simple, the simple template metafunction form does not always interact optimally with the rest of &Cxx;. In particular, the simple metafunction form makes it unnecessarily awkward and tedious to define and work with higher-order metafunctions (metafunctions that operate on other metafunctions). In order to pass a simple metafunction to another template, we need to use <firstterm>template template parameters</>: -</> - -<programlisting> -<![CDATA[ -// returns F(T1,F(T2,T3)) -template< - template<typename,typename> class F - , typename T1 - , typename T2 - , typename T3 - > -struct apply_twice -{ - typedef typename F< - T1 - , typename F<T2,T3>::type - >::type type; -}; - -// a new metafunction returning a type derived from T1, T2, and T3 -template< - typename T1 - , typename T2 - , typename T3 - > -struct derive3 - : apply_twice<derive,T1,T2,T3> -{ -}; -]]> -</> - -<para> -This looks different, but it seems to work. -<footnote id="note.higherorder"><para>In fact it's already broken: <literal>apply_twice</> doesn't even fit the metafunction concept since it requires a template (rather than a type) as its first parameter, which breaks the metafunction protocol.</></> - -However, things begin to break down noticeably when we want to <quote>return</> a metafunction from our metafunction: -</> - -<programlisting> -<![CDATA[ -// returns G s.t. G(T1,T2,T3) == F(T1,F(T2,T3)) -template< template<typename,typename> class F > -struct compose_self -{ - template< - typename T1 - , typename T2 - , typename T3 - > - struct type - : apply_twice<F,T1,T2,T3> - { - }; -}; -]]> -</> - -<para> -The first and most obvious problem is that the result of applying <literal>compose_self</> is not itself a type, but a template, so it can't be passed in the usual ways to other metafunctions. A more subtle issue, however, is that the metafunction <quote>returned</> is not exactly what we intended. Although it acts just like <literal>apply_twice</>, it differs in one important respect: its identity. In the C++ type system, <literal>compose_self<F>::template type<T,U,V></> is not a synonym for <literal>apply_twice<F,T,U,V></>, and any metaprogram which compared metafunctions would discover that fact. -</> - -<para> -Because &Cxx; makes a strict distinction between type and class template template parameters, reliance on simple metafunctions creates a <quote>wall</> between metafunctions and metadata, relegating metafunctions to the status of second-class citizens. For example, recalling our introduction to type sequences, there's no way to make a <literal>cons</> list of metafunctions: -</> - -<programlisting> -<![CDATA[ -typedef cons<derive, cons<derive3, nil> > derive_functions; // error! -]]> -</> - -<para> -We might consider redefining our <literal>cons</> cell so we can pass <literal>derive</> as the head element: -</> - -<programlisting> -<![CDATA[ -template < - template< template<typename T, typename U> class F - , typename Tail - > -struct cons; -]]> -</> - -<para> -However, now we have another problem: &Cxx; templates are polymorphic with respect to their type arguments, but not with respect to template template parameters. The arity (number of parameters) of any template template parameter is strictly enforced, so we <emphasis>still</> can't embed <literal>derive3</> in a <literal>cons</> list. Moreover, polymorphism <emphasis>between</> types and metafunctions is not supported (the compiler expects one or the other), and as we've seen, the syntax and semantics of <quote>returned</> metafunctions is different from that of returned types. Trying to accomplish everything with the simple template metafunction form would seriously limit the applicability of higher-order metafunctions and would have an overall negative effect on the both conceptual and implementation clarity, simplicity and size of the library. -</> -</section> - -<!-- ||||||||||||||||||||||||||||| subsection --> -<section id="metafunctions.classes"> -<title>Metafunction classes</> - -<para> -Fortunately, the truism that <quote>there is no problem in software which can't be solved by adding yet another level of indirection</> applies here. To elevate metafunctions to the status of first-class objects, the &MPL; introduces the concept of a <quote>metafunction class</>: -</> - -<programlisting> -<![CDATA[ -// metafunction class form of derive -struct derive -{ - template< typename N1, typename N2 > - struct apply - { - struct type : N1, N2 {}; - }; -}; -]]> -</> - -<para> -This form should look familiar to anyone acquainted with function objects in STL, with the nested <literal>apply</> template taking the same role as the runtime function-call operator. In fact, compile-time metafunction classes have the same relationship to metafunctions that runtime function objects have to functions: -</> - -<programlisting> -<![CDATA[ -// function form of add -template< typename T > T add(T x, T y) { return x + y; } - -// function object form of add -struct add -{ - template< typename T > - T operator()(T x, T y) { return x + y; } -}; -]]> -</> - -</section> - -<!-- ||||||||||||||||||||||||||||| subsection --> -<section id="metafunctions.onesize"> -<title>One size fits all?</> - -<para> -The metafunction class form solves all the problems with ordinary template metafunction mentioned earlier: since it is a regular class, it can be placed in compile-time metadata sequences and manipulated by other metafunctions using the same protocols as for any other metadata. We thereby avoid the code-duplication needed to provide versions of each library component to operate on ordinary metadata and on metafunctions with each distinct supported arity. -</> - -<para> -On the other hand, it seems that accepting metafunction classes as <emphasis>the</> representation for compile-time function entities imposes code duplication danger as well: if the library's own primitives, algorithms, etc. are represented as class templates, that means that one either cannot reuse these algorithms in the context of higher-order functions, or she have to duplicate all algorithms in the second form, so, for instance, there would be two versions of <literal>find</>: -</> - -<programlisting> -<![CDATA[ -// user-friendly form -template< - typename Sequence - , typename T - > -struct find -{ - typedef /* ... */ type; -}; - -// "metafunction class" form -struct find_func -{ - template< typename Sequence, typename T > - struct apply - { - typedef /* ... */ type; - }; -}; -]]> -</> - -<para> -Of course, the third option is to eliminate <quote>user-friendly form</> completely so one would always have to write: -</> - -<programlisting> -<![CDATA[ -typedef mpl::find::apply<list,long>::type iter; -// or, if one prefers, -// typedef mpl::apply< mpl::find,list,long >::type iter; -]]> -</> - -<para> -instead of -</> - -<programlisting> -<![CDATA[ -typedef mpl::find<list,long>::type iter; -]]> -</> - -<para> -That too would hurt usability, considering that the direct invocations of library's algorithms are far more often-used than passing algorithms as arguments to other algorithms/metafunctions. -</> -</section> - -<!-- ||||||||||||||||||||||||||||| subsection --> -<section id="metafunctions.lambda"> -<title>From metafunction to metafunction class</> - -<para> -The &MPL;'s answer to this dilemma is <firstterm>lambda expressions</>. Lambda is the mechanism that enables the library to curry metafunctions and convert them into metafunction classes, so when one wants to pass the <literal>find</> algorithm as an argument to a higher-order metafunction, she just write: -</> - -<programlisting> -<![CDATA[ -using namespace mpl::placeholder; -typedef mpl::apply< my_f, mpl::find<_1,_2> >::type result; -]]> -</> - -<para> -where <literal>_1</> and <literal>_2</> are placeholders for the first and second arguments to the resulting metafunction class. This preserves the intuitive syntax below for when the user wants to use <literal>find</> directly in her code: -</> - -<programlisting> -<![CDATA[ -typedef mpl::find<list,long>::type iter; -]]> -</> - -<para> -Lambda facility is described in more details in <xref linkend="lambda">. -</> - -</section> - -</section> diff --git a/doc/paper/src/references.sgml b/doc/paper/src/references.sgml deleted file mode 100644 index 0754a9c..0000000 --- a/doc/paper/src/references.sgml +++ /dev/null @@ -1,247 +0,0 @@ -<bibliography id="refs"> -<title>References</> - -<biblioentry id="ref.Abr01"> - <abbrev>Abr01</> - <authorgroup> - <author><firstname>David</><surname>Abrahams</></> - <author><firstname>Carlos Pinto</><surname>Coelho</></> - </> - <title><ulink url="http://users.rcn.com/abrahams/instantiation_speed/index.html">Effects of Metaprogramming Style on Compilation Time</></> - <date>2001</> -</biblioentry> - -<biblioentry id="ref.Ale01"> - <abbrev>Ale01</> - <author><firstname>Andrei</><surname>Alexandrescu</></> - <title>Modern C++ Design: Generic Programming and Design Patterns Applied</> - <publishername>Addison-Wesley</> - <isbn>0-201-70431-5</> - <date>2001</> -</biblioentry> - -<biblioentry id="ref.CE98"> - <abbrev>CE98</> - <authorgroup> - <author><firstname>Krzysztof</><surname>Czarnecki</></> - <author><firstname>Ulrich</><surname>Eisenecker</></> - </> - <title>Metalisp</> - <bibliomisc><ulink url="http://home.t-online.de/home/Ulrich.Eisenecker/meta.htm"></></> -</biblioentry> - -<biblioentry id="ref.CE00"> - <abbrev>CE00</> - <authorgroup> - <author><firstname>Krzysztof</><surname>Czarnecki</></> - <author><firstname>Ulrich</><surname>Eisenecker</></> - </> - <title>Generative Programming: Methods, Tools, and Applications</> - <publishername>Addison-Wesley</> - <isbn>0-201-30977-7</> - <date>2000</> -</biblioentry> - -<biblioentry id="ref.EBNF"> - <abbrev>EBNF</> - <title>ISO/IEC 14977:1996(E), Information technology — Syntactic metalanguage — Extended BNF</> - <orgname>ISO/IEC</> - <date>1996</> -</biblioentry> - -<biblioentry id="ref.GHJ95"> - <abbrev>GHJ+95</> - <authorgroup> - <author><firstname>Erich</><surname>Gamma</></> - <author><firstname>Richard</><surname>Helm</></> - <author><firstname>Ralph</><surname>Johnson</></> - <author><firstname>John</><surname>Vlissides</></> - </> - <title>Design Patterns, Elements of Reusable Object-Oriented Software</> - <publishername>Addison-Wesley</> - <isbn>0-201-63361-2</> - <date>1995</> -</biblioentry> - -<biblioentry id="ref.HU79"> - <abbrev>HU79</> - <authorgroup> - <author><surname>Hopcroft</></> - <author><surname>Ullman</></> - </> - <title>Introduction to automata theory, languages and computations</> - <publishername>Addison-Wesley</> - <date>1979</> -</biblioentry> - -<biblioentry id="ref.Hud89"> - <abbrev>Hud89</> - <author><firstname>Paul</><surname>Hudak</></> - <title>Conception, Evolution, and Application of Functional Programming Languages</> - <biblioset relation='journal'> - <title>ACM Computing Surveys</> - <publishername>Association for Computing Machinery (ACM)</> - <issn>0360-0300</> - </> - <volumenum>21</> - <issuenum>3</> - <pagenums>359-411</> - <date>September, 1989</> -</biblioentry> - -<biblioentry id="ref.Hun91"> - <abbrev>Hun91</> - <author><firstname>Immo</><surname>Huneke</></> - <title>Finite State Machines: A Model of Behavior for C++</> - <biblioset relation='journal'> - <title>C++ Report</> - <publishername>SIGS Publications Inc.</> - <issn>1040-6042</> - </> - <date>1991</> -</biblioentry> - -<biblioentry id="ref.ISO98"> - <abbrev>ISO98</> - <title>ISO/IEC 14882:1998(E), Programming languages — C++</> - <orgname>ISO/IEC</> - <date>1998</> -</biblioentry> - -<biblioentry id="ref.Joh79"> - <abbrev>Joh79</> - <author><firstname>Stephen C.</><surname>Johnson</></> - <title><ulink url="http://dinosaur.compilertools.net/yacc/index.html">Yacc: Yet Another Compiler Compiler</></> - <publishername>UNIX Programmer's Manual</> - <volumenum>2b</> - <pagenums>353-387</> - <date>1979</> -</biblioentry> - -<biblioentry id="ref.Laf00"> - <abbrev>Laf00</> - <author><firstname>David</><surname>Lafreniere</></> - <title><ulink url="http://www.cuj.com/articles/2000/0005/0005f/0005f.htm?topic=articles">State Machine Design in C++</></> - <biblioset relation='journal'> - <title>C/C++ User Journal</> - <publishername>CMP Media LCC</> - <issn>1075-2838</> - </> - <volumenum>18</> - <issuenum>5</> - <date>May 1998</> -</biblioentry> - -<biblioentry id="ref.Loki"> - <abbrev>Loki</> - <title>The Loki library</> - <bibliomisc><ulink url="http://sourceforge.net/projects/loki-lib/"></></> -</biblioentry> - -<biblioentry id="ref.Mar98"> - <abbrev>Mar98</> - <author><firstname>Robert C.</><surname>Martin</></> - <title><ulink url="http://www.objectmentor.com/resources/articles/umlfsm.pdf">UML Tutorial: Finite State Machines</></> - <biblioset relation='journal'> - <title>C++ Report</> - <publishername>SIGS Publications Inc.</> - <issn>1040-6042</> - </> - <date>June 1998</> -</biblioentry> - -<biblioentry id="ref.MPLR"> - <abbrev>MPLR</> - <title>Boost MPL Library Reference Documentation</> - <bibliomisc><ulink url="http://www.mywikinet.com/mpl/ref/Table_of_Content.html"></></> -</biblioentry> - -<biblioentry id="ref.PRE"> - <abbrev>PRE</> - <author><firstname>Vesa</><surname>Karvonen</></> - <title>Boost Preprocessor Metaprogramming library</> - <bibliomisc><ulink url="http://www.boost.org/libs/preprocessor/doc/"></></> -</biblioentry> - -<biblioentry id="ref.SMC"> - <abbrev>SMC</> - <author><firstname>Robert C.</><surname>Martin</></> - <title>SMC - Finite State Machine Compiler (C++)</> - <bibliomisc><ulink url="http://www.objectmentor.com/resources/downloads/index"></></> -</biblioentry> - -<biblioentry id="ref.STL94"> - <abbrev>STL94</> - <authorgroup> - <author><surname>A. A. Stepanov</></> - <author><surname>M. Lee</></> - </authorgroup> - <title>The Standard Template Library</> - <orgname>Hewlett-Packard Laboratories</> - <date>1994</> -</biblioentry> - -<biblioentry id="ref.SPL"> - <abbrev>SPL</> - <title>Boost Smart Pointer library</> - <bibliomisc><ulink url="http://www.boost.org/libs/smart_ptr/"></></> -</biblioentry> - -<biblioentry id="ref.SS75"> - <abbrev>SS75</> - <authorgroup> - <author><firstname>Gerald J.</><surname>Sussman</></> - <author><firstname>Guy L.</><surname>Steele Jr.</></> - </> - <title>Scheme: An interpreter for extended lambda calculus</> - <biblioset relation='journal'> - <title>MIT AI Memo 349</> - <publishername>Massachusetts Institute of Technology</> - </> - <date>May 1975</> -</biblioentry> - -<biblioentry id="ref.TTL"> - <abbrev>TTL</> - <title>Boost Type Traits library</> - <bibliomisc><ulink url="http://www.boost.org/libs/type_traits/"></></> -</biblioentry> - -<biblioentry id="ref.vel95a"> - <abbrev>Vel95a</> - <author><firstname>Todd</><surname>Veldhuizen</></> - <title><ulink url="http://osl.iu.edu/~tveldhui/papers/Template-Metaprograms/meta-art.html">Using C++ template metaprograms</></> - <biblioset relation='journal'> - <title>C++ Report</> - <publishername>SIGS Publications Inc.</> - <issn>1040-6042</> - </> - <volumenum>7</> - <issuenum>4</> - <pagenums>36-43</> - <date>May 1995</> -</biblioentry> - -<biblioentry id="ref.Vel95b"> - <abbrev>Vel95b</> - <author><firstname>Todd</><surname>Veldhuizen</></> - <title><ulink url="http://osl.iu.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html">Expression templates</></> - <biblioset relation='journal'> - <title>C++ Report</> - <publishername>SIGS Publications Inc.</> - <issn>1040-6042</> - </> - <volumenum>7</> - <issuenum>5</> - <pagenums>26-31</> - <date>Jun 1995</> -</biblioentry> - -<biblioentry id="ref.Unr"> - <abbrev>Unr</> - <author><firstname>Erwin</><surname>Unruh</></> - <title>Prime number computation</> - <publishername>ANSI X3J16-94-0075/ISO WG21-462</> -</biblioentry> - -</bibliography> diff --git a/doc/paper/src/sequences.sgml b/doc/paper/src/sequences.sgml deleted file mode 100644 index 826f329..0000000 --- a/doc/paper/src/sequences.sgml +++ /dev/null @@ -1,566 +0,0 @@ - -<!-- ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| section --> -<section id="sequences"> -<title>Sequences, algorithms, and iterators</> - -<!-- ||||||||||||||||||||||||||||| subsection --> -<section id="sequences.intro"> -<title>Introduction</> - -<para> -Compile-time iteration over a sequence (of types) is one of the basic concepts of template metaprogramming. Differences in types of objects being manipulated is the most common point of variability of similar but not identical code/design, and such designs are the direct target for some metaprogramming. Templates were originally designed to solve this exact problem (e.g. <literal>std::vector</>). However, without predefined abstractions/constructs for manipulating/iterating over <emphasis>sequences</> of types (as opposed to standalone types), and without known techniques for emulating these constructs using the current language facilities, their effect on helping high-level metaprogramming happen has been limited. -</> - -<para> -Czarnecki and Eisenecker <citation><xref linkend="ref.CE98"></>, <citation><xref linkend="ref.CE00"></> were the first to introduce compile-time sequences of types and some simple algorithms on them, although the idea of representing common data structures like trees, lists, etc. at compile time, using class template composition has been around for a while (e.g. most of the expression template libraries build such trees as a part of their expression "parsing" process <citation><xref linkend="ref.Vel95b"></>). Alexandrescu <citation><xref linkend="ref.Ale01"></> used lists of types and some algorithms on them to implement several design patterns; the accompanying code is known as the Loki library <citation><xref linkend="ref.Loki"></>. -</> -</section> - -<!-- ||||||||||||||||||||||||||||| subsection --> -<section id="sequences.algo"> -<title>Algorithms and sequences</> - -<para> -Most of the algorithms in the &BMPL; operate on sequences. For example, searching for a type in a list looks like this: -</> - -<programlisting> -<![CDATA[ -typedef mpl::list<char,short,int,long,float,double> types; -typedef mpl::find<types,long>::type iter; -]]> -</> - -<para> -Here, <literal>find</> accepts two parameters - a sequence to search (<literal>types</>) and the type to search for (<literal>long</>) - and returns an iterator <literal>iter</> pointing to the first element of the sequence such that <literal>iter::type</> is identical to <literal>long</>. If no such element exists, <literal>iter</> is identical to <literal>end<types>::type</>. Basically, this is how one would search for a value in a <literal>std::list</> or <literal>std::vector</>, except that <literal>mpl::find</> accepts the sequence as a single parameter, while <literal>std::find</> takes two iterators. Everything else is pretty much the same - the names are the same, the semantics are very close, there are iterators, and one can search not only by type, but also by using a predicate: -</> - -<programlisting> -<![CDATA[ -typedef mpl::find_if< types,boost::is_float<_> >::type iter; -]]></> - -<para> -This conceptual/syntactical similarity with the STL is not coincidental. Reusing the conceptual framework of the STL in the compile-time world allows us to apply familiar and sound approaches for dealing with sequential data structures. The algorithms and idioms which programmers already know from the STL can be applied again at compile-time. We consider this to be one of &MPL;'s greatest strengths, distinguishing it from earlier attempts to build a template metaprogramming library. -</> -</section> - -<!-- ||||||||||||||||||||||||||||| subsection --> -<section id="sequences.concepts"> -<title>Sequence concepts</> - -<para> -In the <literal>find</> example above, we searched for the type in a sequence built using the <literal>mpl::list</> template; but <literal>list</> is not the only sequence that the library provides. Neither is <literal>mpl::find</> or any other algorithm hard-coded to work only with <literal>list</> sequences. <literal>list</> is just one model of &MPL;'s <phrase role="concept">Forward Sequence</> concept, and <literal>find</> works with anything that satisfies this concept's requirements. The hierarchy of sequence concepts in &MPL; is quite simple - a <phrase role="concept">Sequence</> is any compile-time entity for which <literal>begin<></> and <literal>end<></> produce iterators to the range of its elements; a <phrase role="concept">Forward Sequence</> is a Sequence whose iterators satisfy <phrase role="concept">Forward Iterator</> requirements; a <phrase role="concept">Bidirectional Sequence</> is a Forward Sequence whose iterators satisfy <phrase role="concept">Bidirectional Iterator</> requirements; finally, a <phrase role="concept">Random Access Sequence</> is a Bidirectional Sequence whose iterators satisfy <phrase role="concept">Random Access Iterator</> requirements. - -<footnote id="note.seqconcepts"><para> -A more precise definition of these concepts can be found in the library reference documentation <citation><xref linkend="ref.MPLR"></>. -</></> - -</> - -<para> -Decoupling algorithms from particular sequence implementations (through iterators) allows a metaprogrammer to create her own sequence types and to retain the rest of the library at her disposal. For example, one can define a <literal>tiny_list</> for dealing with sequences of three types as follows: -</> - -<programlisting> -<![CDATA[ -template< typename TinyList, long Pos > -struct tiny_list_item; - -template< typename TinyList, long Pos > -struct tiny_list_iterator -{ - typedef typename tiny_list_item<TinyList,Pos>::type type; - typedef tiny_list_iterator<TinyList, Pos-1> prior; - typedef tiny_list_iterator<TinyList, Pos+1> next; -}; - -template< typename T0, typename T1, typename T2 > -struct tiny_list -{ - typedef tiny_list_iterator<tiny_list, 0> begin; - typedef tiny_list_iterator<tiny_list, 3> end; - typedef T0 type0; - typedef T1 type1; - typedef T2 type2; -}; - -template< typename TinyList > -struct tiny_list_item<TinyList,0> -{ - typedef typename TinyList::type0 type; -}; - -template< typename TinyList > -struct tiny_list_item<TinyList,1> -{ - typedef typename TinyList::type1 type; -}; - -template< typename TinyList > -struct tiny_list_item<TinyList,2> -{ - typedef typename TinyList::type2 type; -}; -]]> -</> - -<para> -and then use it with any of the library algorithms as if it were <literal>mpl::list</>: -</> - -<programlisting> -<![CDATA[ -typedef tiny_list< char,short,int > types; -typedef mpl::transform< - types - , boost::add_pointer<_1> - >::type pointers; -]]> -</> - -<para> -Note that <literal>tiny_list</> is a model of Bidirectional Sequence; it would be a Random Access Sequence if we added <literal>advance</> and <literal>distance</> members to <literal>tiny_list_iterator</>: -</> - -<programlisting> -<![CDATA[ -template< typename TinyList, long Pos > -struct tiny_list_iterator -{ - static long const position = Pos; - - typedef typename tiny_list_item<TinyList,Pos>::type type; - typedef tiny_list_iterator<TinyList, Pos-1> prior; - typedef tiny_list_iterator<TinyList, Pos+1> next; - - template< typename N > struct advance - { - typedef tiny_list_iterator< - TinyList - , Pos + N::value - > type; - }; - - template< typename Other > struct distance - { - typedef mpl::integral_c< - long - , Other::position - position - > type; - }; -}; -]]> -</> - -<para> -While the <literal>tiny_list</> itself might be not that interesting (after all, it can hold only three elements), if the technique above could be automated so we would be able to define not-so-tiny sequences (with five, ten, twenty, etc. elements), it would be very valuable. - -<footnote id="note.tinylist"><para> -Random access is almost as important at compile-time as it is at run-time. For example, searching for an item in a sorted random-access sequence using <literal>lower_bound</> can be much faster than performing the same operation on a forward-access-only <literal>list</>. -</></> - -</> - -<para> -External code generation is an option, but there exists a solution within the language. However, it is not a template metaprogramming, but rather <emphasis>preprocessor metaprogramming</>. In fact, &MPL;'s <literal>vector</> - a fixed-size type sequence that provides random-access iterators - is implemented very much like the above <literal>tiny_list</> - using the Boost Preprocessor library <citation><xref linkend="ref.PRE"></>. -</> -</section> - -<!-- ||||||||||||||||||||||||||||| subsection --> -<section id="sequences.revisited"> -<title>Ad hoc example revisited</> - -<para> -So, the library provides its users with almost complete compile-time equivalent of the STL framework. Does it help them to solve their metaprogramming tasks? Let's return to our earlier <link linkend="example.largest"><literal>largest</></> example to see if we can rewrite it in a better way with what &MPL; has to offer. Well, actually, there is not much to look at, because the &MPL; implementation is a one-liner (we'll spread it out here for readability) - -<footnote id="note.maxelement"><para>Here is another, even more elegant implementation:</> -<programlisting> -<![CDATA[ -template< typename Sequence > -struct largest -{ - typedef typename mpl::max_element< - mpl::transform_view< - Sequence - , mpl::sizeof_<_> - > - >::type type; -}; -]]></> -</> - -: -</> - -<programlisting> -<![CDATA[ -template< typename Sequence > -struct largest -{ - typedef typename mpl::max_element< - Sequence - mpl::less< - mpl::sizeof_<_1> - , mpl::sizeof_<_2> - > - >::type iter; - - typedef typename iter::type type; -}; -]]></> - -<para> -There are no more termination conditions with tricky pattern matching, no more partial specializations; and even more importantly, it's <emphasis>obvious</> what the above code does - even although it's all templates - something that one could not say about the original version. -</> -</section> - -<!-- ||||||||||||||||||||||||||||| subsection --> -<section id="sequences.iterfold"> -<title>iter_fold as the main iteration algorithm</> - -<para> -For the purpose of examining a little bit more of the library's internal structure, let's look at how <literal>max_element</> from the above example is implemented. One might expect that <emphasis>now</> we will again see all these awkward partial specializations, esoteric pattern matching, etc. Well, let's see: -</> - -<programlisting> -<![CDATA[ -template< - typename Sequence - , typename Predicate - > -struct max_element -{ - typedef typename mpl::iter_fold< - Sequence - , typename mpl::begin<Sequence>::type - , if_< less< deref<_1>,deref<_2> >, _2, _1 > - >::type type; -}; -]]> -</> - -<para> -The first thing to notice here is that this algorithm is implemented in terms of another one: <literal>iter_fold</>. In fact, this is probably the most important point of the example, because nearly all other generic sequence algorithms in the library are implemented in terms of <literal>iter_fold</>. If a user should ever need to implement her own sequence algorithm, she'll almost certainly be able to do so using this primitive, which means she won't have to resort to implementing hand-crafted iteration, pattern matching of special cases for loop termination, or workarounds for lack of partial specialization. It also means that her algorithm will automatically benefit from any optimizations the library has implemented, (e.g. recursion unrolling), and that it will work with any sequence that is a model of ForwardSequence, because <literal>iter_fold</> does not require anything more of its sequence argument. -</> - -<para> -<literal>iter_fold</> algorithm is basically a compile-time equivalent of the <literal>fold</> or <literal>reduce</> functions that comprise the basic and well-known primitives of many functional programming languages. An analogy more familiar to a &Cxx; programmer would be the <literal>std::accumulate</> algorithm from the &Cxx; standard library (<citation><xref linkend="ref.ISO98"></>, section 26.4.1 [lib.accumulate]). However, <literal>iter_fold</> is designed to take advantage of the natural characteristics of recursive traversal: it accepts <emphasis>two</> metafunction class arguments, the first of which is applied to the state "on the way in" and the second of which is applied "on the -way out". -</> - -<para> -The interface to <literal>iter_fold</> is defined in &MPL; as follows: -</> - -<programlisting> -<![RCDATA[ -template< - typename Sequence - , typename InitialState - , typename ForwardOp - , typename BackwardOp = _1 - > -struct iter_fold -{ - typedef &unspec; type; -}; -]]> -</> - -<para> -The algorithm <quote>returns</> the result of two-way successive applications of binary <literal>ForwardOp</> and <literal>BackwardOp</> operations to iterators in range [<literal>begin<Sequence>::type</>, <literal>end<Sequence>::type</>) and previous result of an operation; the <literal>InitialState</> is logically placed before the sequence and included in the forward traversal. The result <literal>type</> is identical to <literal>InitialState</> if the sequence is empty. -</> - -<para> -The library also provides <literal>iter_fold_backward</>, <literal>fold</>, and <literal>fold_backward</> algorithms which wrap <literal>iter_fold</> to accommodate its most common usage patterns. -</> -</section> - -<!-- ||||||||||||||||||||||||||||| subsection --> -<section id="sequences.numbers"> -<title>Sequences of numbers</> - -<para> -What we've seen so far were sequences (and algorithms on sequences) of types. It is both possible and easy to manipulate compile-time <emphasis>values</> using the library as well. The only thing to remember is that in &Cxx;, class template non-type template parameters give us one more example of non-polymorphic behavior. In other words, if one declared a metafunction to take a non-type template parameter (e.g. <literal>long</>) it's not possible to pass anything besides compile-time integral constants to it: -</> - -<programlisting> -<![CDATA[ -template< long N1, long N2 > -struct equal_to -{ - static bool const value = (N1 == N2); -}; - -equal_to<5,5>::value; // ok -equal_to<int,int>::value; // error! -]]> -</> - -<para> -And of course this doesn't work the other way around either: -</> - -<programlisting> -<![CDATA[ -typedef mpl::list<1,2,3,4,5> numbers; // error! -]]> -</> - -<para> -While this may be an obvious limitation, it imposes yet another dilemma on the library design: on the one hand, we don't want to restrict users to type manipulations only, and on the other hand, full support for integral manipulations would require at least duplication of most of the library facilities - -<footnote id="note.nontype"><para>Ideally, if going this route, all the templates should be re-implemented for every integral type - <literal>char</>, <literal>int</>, <literal>short</>, <literal>long</>, etc. -</></> - -- the same situation as we would have if we had chosen to represent metafunctions as ordinary class templates. The solution for this issue is the same as well: we represent integral values by wrapping them in types - -<footnote id="note.valuewrapping"><para> -The same technique was suggested by Czarnecki and Eisenecker in <citation><xref linkend="ref.CE00"></>. -</></> - -. For example, to create a list of numbers one can write: -</> - -<programlisting> -<![CDATA[ -typedef mpl::list< - mpl::int_c<1> - , mpl::int_c<2> - , mpl::int_c<3> - , mpl::int_c<4> - , mpl::int_c<5> - > numbers; -]]> -</> - -<para> -Wrapping integral constants into types to make them first-class citizens is important well inside metaprograms, -where one often doesn't know (and doesn't care) if the metafunctions she is using operate on types, integral values, other metafunctions, or something else, like fixed-point or rational numbers (<literal>mpl::fixed_c</> and <literal>mpl::rational_c</>). -</> - -<para> -But, from the user's perspective, the above example is much more verbose than the shorter, incorrect one. Thus, for the purpose of convenience, the library does provide users with a template that takes non-type template parameters, but offers a more compact notation: -</> - -<programlisting> -<![CDATA[ -typedef mpl::list_c<long,1,2,3,4,5> numbers; -]]></> - -<para> -There is a similar <literal>vector</> counterpart as well: -</> - -<programlisting> -<![CDATA[ -typedef mpl::vector_c<long,1,2,3,4,5> numbers; -]]> -</> -</section> - -<!-- ||||||||||||||||||||||||||||| subsection --> -<section id="sequences.variety"> -<title>A variety of sequences</> - -<para> -Previous efforts to provide generalized metaprogramming facilities for &Cxx; have always concentrated on <literal>cons</>-style type lists and a few core algorithms like <literal>size</> and <literal>at</>, which are tied to the specific sequence implementation. Such systems have an elegant simplicity reminiscent of the analogous functionality in pure functional Lisp. It is much more time-consuming to implement even a basic set of the sequence algorithms provided by equivalent run-time libraries (the STL in particular), but if we have learned anything from the STL, it is that tying those algorithms' implementations to a specific sequence implementation is a misguided effort! -</> - -<para> -The truth is that there is no single <quote>best</> type sequence implementation for the same reasons that there will never be a single <quote>best</> runtime sequence implementation. Furthermore, there are <emphasis>already</> quite a number of type list implementations in use today; and just as the STL algorithms can operate on sequences which don't come from STL containers, so the MPL algorithms are designed to work with foreign type sequences. -</> - -<para> -It may be an eye-opening fact for some that type lists are not the only useful compile-time sequence. Again, the need for a variety of compile-time containers arises for the same reasons that we have lists, vectors, deques, and sets in the &Cxx; standard library — different containers have different functional and performance characteristics which determine not only applicability and efficiency of particular algorithms, but also the expressiveness or verbosity of the code that uses them. While runtime performance is not an issue for &Cxx; metaprograms, compilation speed is often a significant bottleneck to advanced &Cxx; software development <citation><xref linkend="ref.Abr01"></>. -</> - -<para> -The &MPL; provides five built-in sequences: <literal>list</>, <literal>list_c</> (really just a <literal>list</> of value wrappers), <literal>vector</>, a randomly-accessible sequence of fixed maximum size, <literal>vector_c</>, and <literal>range_c</>, a randomly-accessible sequence of consecutive integral values. More important, however, is its ability to adapt to arbitrary sequence types. The only core operations that a sequence is required to provide in order to be used with the library algorithms are <literal>begin<></> and <literal>end<></> metafunctions which "return" iterators into the sequence. As with the STL, it is the iterators which are used to implement most of the general-purpose sequence algorithms the library provides. Also, as with the STL, algorithm specialization is used to take advantage of implementation knowledge about particular sequences: many of the "basic" sequence operations such as <literal>back<></>, <literal>front<></>, <literal>size<></>, and <literal>at<></> are specialized on sequence type to provide a more efficient implementation than the fully generic version. -</> -</section> - -<!-- ||||||||||||||||||||||||||||| subsection --> -<section id="sequences.unrolling"> -<title>Loop/recursion unrolling</> - -<para> -Almost coincidentally, loop unrolling can be as important to compile-time iterative algorithms as it is to runtime algorithms. To see why, one must first remember that all "loops" in &Cxx; metaprograms, are in fact, implemented with recursion, and that the template instantiation depth can be a valuable resource in a compiler implementation. In fact, Annex B of the &Cxx; standard (<citation><xref linkend="ref.ISO98"></>, annex B [limits]) <emphasis>recommends</> a minimum depth of 17 recursively nested template instantiations; but this is far too low for many serious metaprograms, some of which easily exceed the hard-coded instantiation limits of some otherwise excellent compilers. To see how this works in action, let's examine a straightforward implementation of the <literal>fold</> metafunction, which combines some algorithm state with each element of a sequence: -</> - -<programlisting> -<![CDATA[ -namespace aux { - -// unspecialized version combines the initial state and first element -// and recurses to process the rest -template< - typename Start - , typename Finish - , typename State - , typename BinaryFunction - > -struct fold_impl - : fold_impl< - typename Start::next - , Finish - , typename apply< - BinaryFunction - , State - , typename Start::type - >::type - , BinaryFunction - > -{ -}; - -// specialization for loop termination -template< - typename Finish - , typename State - , typename BinaryFunction - > -struct fold_impl<Finish,Finish,State,BinaryFunction> -{ - typedef State type; -}; - -} // namespace aux - -// public interface -template< - typename Sequence - , typename State - , typename ForwardOp - > -struct fold - : aux::fold_impl< - , typename begin<Sequence>::type - , typename end<Sequence>::type - , State - , typename lambda<ForwardOp>::type - > -{ -}; - -]]> -</> - -<para> -Although simple and elegant, this implementation will always incur at least as many levels of recursive template instantiation as there are elements in the input sequence. - -<footnote id="note.unrolling1"><para>It could be much more, depending on the complexity of the <literal>apply<...></> expression, whose depth is added to the overall recursion depth. -</></> - -The library addresses this problem by explicitly "unrolling" the recursion. To apply the technique to our <literal>fold</> example, we begin by factoring out a single step of the algorithm. Our <literal>fold_impl_step</> metafunction has two results: <literal>type</> (the next state), and <literal>iterator</> (the next sequence position). -</> - -<programlisting> -<![CDATA[ -template< - typename BinaryFunction - , typename State - , typename Start - , typename Finish - > -struct fold_impl_step -{ - typedef typename apply< - BinaryFunction - , State - , typename Start::type - >::type type; - - typedef typename Start::next iterator; -}; -]]> -</> - -<para> -As with our main algorithm implementation, we specialize for the loop termination condition so that the step becomes a no-op: -</> - -<programlisting> -<![CDATA[ -template< - typename BinaryFunction - , typename State - , typename Finish - > -struct fold_impl_step<BinaryFunction,State,Finish,Finish> -{ - typedef State type; - typedef Finish iterator; -}; -]]> -</> - -<para> -Now we can now reduce <literal>fold</>'s instantiation depth by any constant factor N simply by inserting N invocations of <literal>fold_impl_step</>. Here we've chosen a factor of 4: -</> - -<programlisting> -<![CDATA[ -template< - typename Start - , typename Finish - , typename State - , typename BinaryFunction - > -struct fold_impl -{ - private: - typedef fold_impl_step< - BinaryFunction - , State - , Start - , Finish - > next1; - - typedef fold_impl_step< - BinaryFunction - , typename next1::type - , typename next1::iterator - , Finish - > next2; - - typedef fold_impl_step< - BinaryFunction - , typename next2::type - , typename next2::iterator - , Finish - > next3; - - typedef fold_impl_step< - BinaryFunction - , typename next3::type - , typename next3::iterator - , Finish - > next4; - - typedef fold_impl_step< - typename next4::iterator - , Finish - , typename next4::type - , BinaryFunction - > recursion; - - public: - typedef typename recursion::type type; -}; -]]> -</> - -<para> -The &MPL; applies this unrolling technique across all algorithms with an unrolling factor tuned according to the demands of the &Cxx; implementation in use, and with an option for the user to override the value. - -<footnote id="note.unrolling2"><para> -This implementation detail is made relatively painless through heavy reliance on the Boost Preprocessor Library, so only one copy of the code needs to be maintained. -</></> - -This fact enables users to push beyond the metaprogramming limits they would usually encounter with more naive algorithm implementations. Experiments also show a small (up to 10%) increase in metaprogram instantiation speed on some compilers when loop unrolling is used. -</> -</section> - -</section> diff --git a/doc/paper/src/typeselection.sgml b/doc/paper/src/typeselection.sgml deleted file mode 100644 index e8be749..0000000 --- a/doc/paper/src/typeselection.sgml +++ /dev/null @@ -1,242 +0,0 @@ - -<!-- ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| section --> -<section id="typeselection"> -<title>Conditional type selection</> - -<para> -Conditional type selection is the simplest basic construct of &Cxx; template metaprogramming. Veldhuizen <citation><xref linkend="ref.Vel95a"></> was the first to show how to implement it, and Czarnecki and Eisenecker <citation><xref linkend="ref.CE00"></> first presented it as a standalone library primitive. The &MPL; defines the corresponding facility as follows: -</> - -<programlisting> -<![RCDATA[ -template< - typename Condition - , typename T1 - , typename T2 - > -struct if_ -{ - typedef &unspec; type; -}; -]]> -</> - -<para> -Note that the first template parameter of the template is a type. -</> - -<programlisting> -<![CDATA[ -// usage/semantics -typedef mpl::if_<mpl::true_c,char,long>::type t1; -typedef mpl::if_<mpl::false_c,char,long>::type t2; - -BOOST_MPL_ASSERT_IS_SAME(t1, char); -BOOST_MPL_ASSERT_IS_SAME(t2, long); -]]> -</> - -<para> -The construct is important because template metaprograms often contain a lot of decision-making code, and, as we will show, spelling it manually every time via (partial) class template specialization quickly becomes impractical. The template is also important from the point of encapsulating the compiler workarounds. -</> - -<!-- ||||||||||||||||||||||||||||| subsection --> -<section id="delayedeval"> -<title>Delayed evaluation</> - -<para> -The way the &Cxx; template instantiation mechanism works imposes some subtle limitations on applicability of the type selection primitive (<literal>if_</>), compared to a manually implemented equivalent of the selection code. For example, suppose we are implementing a <literal>pointed_type</> traits template such that <literal>pointed_type<T>::type</> instantiated for a <literal>T</> that is either a plain pointer (<literal>U*</>), <literal>std::auto_ptr<U></>, or any of the Boost smart pointers <citation><xref linkend="ref.SPL"></>, e.g. <literal>boost::scoped_ptr<U></>, will give us the pointed type (<literal>U</>): -</> - -<programlisting> -<![CDATA[ -BOOST_MPL_ASSERT_IS_SAME(pointed_type<my*>::type, my); -BOOST_MPL_ASSERT_IS_SAME(pointed_type< std::auto_ptr<my> >::type, my); -BOOST_MPL_ASSERT_IS_SAME(pointed_type< boost::scoped_ptr<my> >::type, my); -]]> -</> - -<para> -Unfortunately, the straightforward application of <literal>if_</> to this problem does not work: - -<footnote id="note.pointedtype"><para> -Although it would be easy to implement <literal>pointed_type</> using partial specialization to distinguish the case where <literal>T</> is a pointer, <literal>if_</> is likely to be the right tool for dealing with more complex conditionals. For the purposes of exposition, please suspend disbelief! -</></> - -</> - -<programlisting> -<![CDATA[ -template< typename T > -struct pointed_type - : mpl::if_< - boost::is_pointer<T> - , typename boost::remove_pointer<T>::type - , typename T::element_type // #1 - > -{ -}; - -// the following code causes compilation error in line #1: -// name followed by "::" must be a class or namespace name -typedef pointed_type<char*>::type result; -]]> -</> - -<para> -Clearly, the expression <literal>typename T::element_type</> is not valid in the case of <literal>T == char*</>, and that's what the compiler is complaining about. Implementing the selection code manually solves the problem: -</> - -<programlisting> -<![CDATA[ -namespace aux { -// general case -template< typename T, bool is_pointer = false > -struct select_pointed_type -{ - typedef typename T::element_type type; -}; - -// specialization for plain pointers -template< typename T > -struct select_pointed_type<T,true> -{ - typedef typename boost::remove_pointer<T>::type type; -}; -} - -template< typename T > -struct pointed_type - : aux::select_pointed_type< - T, boost::is_pointer<T>::value - > -{ -}; -]]> -</> - -<para> -But this quickly becomes awkward if needs to be done repeatedly, and this awkwardness is compounded when partial specialization is not available. We can try to work around the problem as follows: -</> - -<programlisting> -<![CDATA[ -namespace aux { -template< typename T > -struct element_type -{ - typedef typename T::element_type type; -}; -} - -template< typename T > -struct pointed_type -{ - typedef typename mpl::if_< - boost::is_pointer<T> - , typename boost::remove_pointer<T>::type - , typename aux::element_type<T>::type - >::type type; -}; -]]> -</> - -<para> -but this doesn't work either - the access to the <literal>aux::element_type<T></>'s nested <literal>type</> member still forces the compiler to instantiate <literal>element_type<T></> with <literal>T == char*</>, and that instantiation is, of course, invalid. Also, although in our case this does not lead to a compile error, the <literal>boost::remove_pointer<T></> template always gets instantiated as well, and for the same reason (because we are accessing its nested <literal>type</> member). Unnecessary instantiation that is not fatal may or may be not a problem, depending on the <quote>weight</> of the template (how much the instantiation taxes the compiler), but a general rule of thumb would be to avoid such code. -</> - -<para> -Returning to our error, to make the above code compile, we need to factor the act of <quote>asking</> <literal>aux::element_type<T></> for its nested <literal>type</> out of the <literal>if_</> invocation. The fact that both the <literal>boost::remove_pointer<T></> trait template and <literal>aux::element_type<T></> use the same naming convention for their result types makes the refactoring easier: -</> - -<programlisting> -<![CDATA[ -template< typename T > -struct pointed_type -{ - private: - typedef typename mpl::if_< - boost::is_pointer<T> - , boost::remove_pointer<T> - , aux::element_type<T> - >::type func_; - - public: - typedef typename func_::type type; -}; -]]> -</> - -<para> -Now the compiler is guaranteed not to instantiate both <literal>boost::remove_pointer<T></> and <literal>aux::element_type<T></>, even although they are used as actual parameters to the <literal>if_</> template, so we are allowed to get away with <literal>aux::element_type<char*></> so long as it won't end up being selected as <literal>func_</>. -</> - -<para> -The above technique is so common in template metaprograms, that it even makes sense to facilitate the selection of a nested <literal>type</> member by introducing a high-level equivalent to <literal>if_</> - the one that will do the <literal>func_::type</> operation (that is called [nullary] metafunction class application) as a part of its invocation. The &MPL; provides such template - it's called <literal>apply_if</>. Using it, we can re-write the above code as simple as: -</> - -<programlisting> -<![CDATA[ -template< typename T > -struct pointed_type -{ - typedef typename mpl::apply_if< - boost::is_pointer<T> - , boost::remove_pointer<T> - , aux::element_type<T> - >::type type; -}; -]]> -</> - -<para> -To make our techniques review complete, let's consider a slightly different example - suppose we want to define a high-level wrapper around <literal>boost::remove_pointer</> traits template <citation><xref linkend="ref.TTL"></>, which will strip the pointer qualification conditionally. We will call it <literal>remove_pointer_if</>: -</> - -<programlisting> -<![CDATA[ -template< - typename Condition - , typename T - > -struct remove_pointer_if -{ - typedef typename mpl::if_< - Condition - , typename boost::remove_pointer<T>::type - , T - >::type type; -}; -]]> -</> - -<para> -Now the above works the first time, but it suffers from the problem we mentioned earlier - <literal>boost::remove_pointer<T></> gets instantiated even if its result is never used. In the metaprogramming world compilation time is an important resource <citation><xref linkend="ref.Abr01"></>, and it is wasted by unnecessary template instantiations. We've just seen how to deal with the problem when both arguments to <literal>if_</> are the results of nullary metafunction class applications, but in this example one of the arguments (<literal>T</>) is just a simple type, so the refactoring just doesn't seem possible. -</> - -<para> -The easiest way out of this situation would be to pass to <literal>if_</> a real nullary metafunction instead of <literal>T</> - the one that returns <literal>T</> on its invocation. The &MPL; provides a simple way to do it - we just substitute <literal>identity<T></> and <literal>apply_if</> for <literal>T</> and <literal>if_</>: -</> - -<programlisting> -<![CDATA[ -template< - typename Condition - , typename T - > -struct remove_pointer_if -{ - typedef typename mpl::apply_if< - Condition - , boost::remove_pointer<T> - , mpl::identity<T> - >::type type; -}; -]]> -</> - -<para> -which gives us exactly what we wanted. -</> -</section> -</section> diff --git a/doc/paper/src/usage.sgml b/doc/paper/src/usage.sgml deleted file mode 100644 index 608edf1..0000000 --- a/doc/paper/src/usage.sgml +++ /dev/null @@ -1,8 +0,0 @@ -<section id="usage"> -<title>Basic usage</> - -&typeselection; -&metafunctions; -&sequences; - -</section> diff --git a/doc/readme b/doc/readme deleted file mode 100644 index a73b439..0000000 --- a/doc/readme +++ /dev/null @@ -1,18 +0,0 @@ - -To re-generate the docs in the exact format as they appear here, you would -need a slightly tweaked DocBook XSLT stylesheets disrtibution available at -http://www.mywikinet.com/mpl/docbook-xsl-1.50.0.zip - -If you are to use the build scripts as-is, you also need these tools: - - sx - an SGML to XML convertor, a part of James Clark's SP package, - available at http://www.jclark.com/sp/ - - msxsl - Microsoft XSLT processor, available at - http://msdn.microsoft.com/library/en-us/dnxml/html/msxsl.asp - - tidy - http://tidy.sourceforge.net/ - - Python - to be able to run 'tidy_attr.py', - available at http://www.python.org or - http://www.activestate.com/Products/ActivePython/ diff --git a/doc/ref/Forward_Sequence.html b/doc/ref/Forward_Sequence.html deleted file mode 100644 index c8d24d0..0000000 --- a/doc/ref/Forward_Sequence.html +++ /dev/null @@ -1,10 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html> -<head> -<meta http-equiv="refresh" content="0; URL=../index.html"> -</head> -<body> -Automatic redirection failed, please go to -<a href="../index.html">../index.html</a>. -</body> -</html> diff --git a/doc/ref/Integral_Constant.html b/doc/ref/Integral_Constant.html deleted file mode 100644 index c8d24d0..0000000 --- a/doc/ref/Integral_Constant.html +++ /dev/null @@ -1,10 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html> -<head> -<meta http-equiv="refresh" content="0; URL=../index.html"> -</head> -<body> -Automatic redirection failed, please go to -<a href="../index.html">../index.html</a>. -</body> -</html> diff --git a/doc/ref/Metafunction.html b/doc/ref/Metafunction.html deleted file mode 100644 index c8d24d0..0000000 --- a/doc/ref/Metafunction.html +++ /dev/null @@ -1,10 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html> -<head> -<meta http-equiv="refresh" content="0; URL=../index.html"> -</head> -<body> -Automatic redirection failed, please go to -<a href="../index.html">../index.html</a>. -</body> -</html> diff --git a/doc/ref/Sequence.html b/doc/ref/Sequence.html deleted file mode 100644 index c8d24d0..0000000 --- a/doc/ref/Sequence.html +++ /dev/null @@ -1,10 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html> -<head> -<meta http-equiv="refresh" content="0; URL=../index.html"> -</head> -<body> -Automatic redirection failed, please go to -<a href="../index.html">../index.html</a>. -</body> -</html> diff --git a/doc/ref/Sequences.html b/doc/ref/Sequences.html deleted file mode 100644 index c8d24d0..0000000 --- a/doc/ref/Sequences.html +++ /dev/null @@ -1,10 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html> -<head> -<meta http-equiv="refresh" content="0; URL=../index.html"> -</head> -<body> -Automatic redirection failed, please go to -<a href="../index.html">../index.html</a>. -</body> -</html> diff --git a/doc/refmanual.html b/doc/refmanual.html new file mode 100644 index 0000000..ee8cd57 --- /dev/null +++ b/doc/refmanual.html @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> +<meta name="generator" content="Docutils 0.3.6: http://docutils.sourceforge.net/" /> +<title>The MPL Reference Manual + + + + +

The MPL Reference Manual

+ +++ + + + + + +
Copyright:Copyright © Aleksey Gurtovoy and David Abrahams, 2001-2005.
License:Distributed under the Boost Software License, Version 1.0. (See +accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt)
+ + + + + diff --git a/doc/refmanual/accumulate.html b/doc/refmanual/accumulate.html new file mode 100644 index 0000000..2975322 --- /dev/null +++ b/doc/refmanual/accumulate.html @@ -0,0 +1,123 @@ + + + + + + +The MPL Reference Manual: accumulate + + + + + +
Front Page / Algorithms / Iteration Algorithms / accumulate
+
+

accumulate

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename State
+    , typename ForwardOp
+    >
+struct accumulate
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the result of the successive application of binary ForwardOp to the +result of the previous ForwardOp invocation (State if it's the first call) +and every element of the sequence in the range [begin<Sequence>::type, end<Sequence>::type) in order. +[Note: accumulate is a synonym for fold — end note]

+
+
+

Header

+
+#include <boost/mpl/accumulate.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceA sequence to iterate.
StateAny typeThe initial state for the first ForwardOp +application.
ForwardOpBinary Lambda ExpressionThe operation to be executed on forward +traversal.
+
+
+

Expression semantics

+

For any Forward Sequence s, binary Lambda Expression op, and arbitrary type state:

+
+typedef accumulate<s,state,op>::type t; 
+
+ +++ + + + + + +
Return type:A type.
Semantics:

Equivalent to

+
+typedef fold<s,state,op>::type t; 
+
+
+
+
+

Complexity

+

Linear. Exactly size<s>::value applications of op.

+
+
+

Example

+
+typedef vector<long,float,short,double,float,long,long double> types;
+typedef accumulate<
+      types
+    , int_<0>
+    , if_< is_float<_2>,next<_1>,_1 >
+    >::type number_of_floats;
+
+BOOST_MPL_ASSERT_RELATION( number_of_floats::value, ==, 4 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/acknowledgements.html b/doc/refmanual/acknowledgements.html new file mode 100644 index 0000000..eb3dda2 --- /dev/null +++ b/doc/refmanual/acknowledgements.html @@ -0,0 +1,24 @@ + + + + + + +The MPL Reference Manual: Acknowledgements + + + + + +
Front Page / Acknowledgements
+
+

Acknowledgements

+

The format and language of this reference documentation has been greatly influenced by +the SGI's Standard Template Library Programmer's Guide.

+ +
+ + + + + diff --git a/doc/refmanual/advance.html b/doc/refmanual/advance.html new file mode 100644 index 0000000..02c8823 --- /dev/null +++ b/doc/refmanual/advance.html @@ -0,0 +1,138 @@ + + + + + + +The MPL Reference Manual: advance + + + + + +
Front Page / Iterators / Iterator Metafunctions / advance
+
+

advance

+
+

Synopsis

+
+template<
+      typename Iterator
+    , typename N
+    >
+struct advance
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Moves Iterator by the distance N. For bidirectional and +random access iterators, the distance may be negative.

+
+
+

Header

+
+#include <boost/mpl/advance.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
IteratorForward IteratorAn iterator to advance.
NIntegral ConstantA distance.
+
+ +
+

Expression semantics

+

For a Forward Iterator iter and arbitrary Integral Constant n:

+
+typedef advance<iter,n>::type j; 
+
+ +++ + + + + + + + + + +
Return type:Forward Iterator.
Precondition:If Iterator is a Forward Iterator, n::value must be nonnegative.
Semantics:

Equivalent to:

+
+typedef iter i0; 
+typedef next<i0>::type i1; 
+...
+typedef next<in-1>::type j;
+
+

if n::value > 0, and

+
+typedef iter i0; 
+typedef prior<i0>::type i1; 
+...
+typedef prior<in-1>::type j;
+
+

otherwise.

+
Postcondition:j is dereferenceable or past-the-end; +distance<iter,j>::value == n::value if n::value > 0, and +distance<j,iter>::value == n::value otherwise.
+
+
+

Complexity

+

Amortized constant time if iter is a model of +Random Access Iterator, otherwise linear time.

+
+
+

Example

+
+typedef range_c<int,0,10> numbers;
+typedef begin<numbers>::type first;
+typedef end<numbers>::type last;
+
+typedef advance<first,int_<10> >::type i1;
+typedef advance<last,int_<-10> >::type i2;
+
+BOOST_MPL_ASSERT(( boost::is_same<i1,last> ));
+BOOST_MPL_ASSERT(( boost::is_same<i2,first> ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/algorithms-concepts.html b/doc/refmanual/algorithms-concepts.html new file mode 100644 index 0000000..17c73fe --- /dev/null +++ b/doc/refmanual/algorithms-concepts.html @@ -0,0 +1,26 @@ + + + + + + +The MPL Reference Manual: Concepts + + + + + +
Front Page / Algorithms / Concepts
+ + + + + + diff --git a/doc/refmanual/algorithms.html b/doc/refmanual/algorithms.html new file mode 100644 index 0000000..121f45d --- /dev/null +++ b/doc/refmanual/algorithms.html @@ -0,0 +1,59 @@ + + + + + + +The MPL Reference Manual: Algorithms + + + + + +
Front Page / Algorithms
+
+

Algorithms

+

The MPL provides a broad range of fundamental algorithms aimed to +satisfy the majority of sequential compile-time data processing +needs. The algorithms include compile-time counterparts +of many of the STL algorithms, iteration algorithms borrowed from +functional programming languages, and more.

+

Unlike the algorithms in the C++ Standard Library, which operate on +implict iterator ranges, the majority of MPL counterparts take +and return sequences. This derivation is not dictated by the +functional nature of C++ compile-time computations per se, but +rather by a desire to improve general usability of the library, +making programming with compile-time data structures as enjoyable +as possible.

+ +

In the spirit of the STL, MPL algorithms are generic, meaning +that they are not tied to particular sequence class +implementations, and can operate on a wide range of arguments as +long as they satisfy the documented requirements. The requirements +are formulated in terms of concepts. Under the hood, +algorithms are decoupled from concrete sequence +implementations by operating on Iterators.

+

All MPL algorithms can be sorted into three +major categories: iteration algorithms, querying algorithms, and +transformation algorithms. The transformation algorithms introduce +an associated Inserter concept, a rough equivalent for the notion of +Output Iterator in the Standard Library. Moreover, every +transformation algorithm provides a reverse_ counterpart, +allowing for a wider range of efficient transformations — a +common functionality documented by the Reversible Algorithm +concept.

+ + +
+ + + + + diff --git a/doc/refmanual/always.html b/doc/refmanual/always.html new file mode 100644 index 0000000..d47550e --- /dev/null +++ b/doc/refmanual/always.html @@ -0,0 +1,108 @@ + + + + + + +The MPL Reference Manual: always + + + + + +
Front Page / Metafunctions / Miscellaneous / always
+
+

always

+
+

Synopsis

+
+template< 
+      typename X
+    >
+struct always
+{
+    // unspecified
+    // ...
+};
+
+
+
+

Description

+

always<X> specialization is a variadic Metafunction Class always returning the +same type, X, regardless of the number and types of passed arguments.

+
+
+

Header

+
+#include <boost/mpl/always.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
XAny typeA type to be returned.
+
+
+

Expression semantics

+

For an arbitrary type x:

+
+typedef always<x> f;
+
+ +++ + + + + + +
Return type:Metafunction Class.
Semantics:

Equivalent to

+
+struct f : bind< identity<_1>, x > {};
+
+
+
+
+

Example

+
+typedef always<true_> always_true;
+
+BOOST_MPL_ASSERT(( apply< always_true,false_> ));
+BOOST_MPL_ASSERT(( apply< always_true,false_,false_ > ));
+BOOST_MPL_ASSERT(( apply< always_true,false_,false_,false_ > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/and.html b/doc/refmanual/and.html new file mode 100644 index 0000000..375f080 --- /dev/null +++ b/doc/refmanual/and.html @@ -0,0 +1,126 @@ + + + + + + +The MPL Reference Manual: and_ + + + + + +
Front Page / Metafunctions / Logical Operations / and_
+
+

and_

+
+

Synopsis

+
+template< 
+      typename F1
+    , typename F2
+    ...
+    , typename Fn = unspecified
+    >
+struct and_
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the result of short-circuit logical and (&&) operation on its arguments.

+
+
+

Header

+
+#include <boost/mpl/and.hpp>
+#include <boost/mpl/logical.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
F1, F2,... FnNullary MetafunctionOperation's arguments.
+
+
+

Expression semantics

+

For arbitrary nullary Metafunctions f1, f2,... fn:

+
+typedef and_<f1,f2,...,fn>::type r;
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:r is false_ if either of f1::type::value, f2::type::value,... +fn::type::value expressions evaluates to false, and true_ otherwise; +guarantees left-to-right evaluation; the operands subsequent to the first +fi metafunction that evaluates to false are not evaluated.
+ +
+typedef and_<f1,f2,...,fn> r;
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+struct r : and_<f1,f2,...,fn>::type {};
+
+
+
+
+

Example

+
+struct unknown;
+
+BOOST_MPL_ASSERT(( and_< true_,true_ > ));
+BOOST_MPL_ASSERT_NOT(( and_< false_,true_ > ));
+BOOST_MPL_ASSERT_NOT(( and_< true_,false_ > ));
+BOOST_MPL_ASSERT_NOT(( and_< false_,false_ > ));
+BOOST_MPL_ASSERT_NOT(( and_< false_,unknown > )); // OK
+BOOST_MPL_ASSERT_NOT(( and_< false_,unknown,unknown > )); // OK too
+
+
+ +
+ + + + + diff --git a/doc/refmanual/apply-wrap.html b/doc/refmanual/apply-wrap.html new file mode 100644 index 0000000..0c2e853 --- /dev/null +++ b/doc/refmanual/apply-wrap.html @@ -0,0 +1,151 @@ + + + + + + +The MPL Reference Manual: apply_wrap + + + + + +
Front Page / Metafunctions / Invocation / apply_wrap
+
+

apply_wrap

+
+

Synopsis

+
+template< 
+      typename F
+    >
+struct apply_wrap0
+{
+    typedef unspecified type;
+};
+
+template< 
+      typename F, typename A1
+    >
+struct apply_wrap1
+{
+    typedef unspecified type;
+};
+
+...
+
+template< 
+      typename F, typename A1,... typename An
+    >
+struct apply_wrapn
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Invokes a Metafunction Class F with arguments A1,... An.

+

In essence, apply_wrap forms are nothing more than syntactic wrappers around +F::apply<A1,... An>::type / F::apply::type expressions (hence the name). +They provide a more concise notation and higher portability than their +underlaying constructs at the cost of an extra template instantiation.

+
+
+

Header

+
+#include <boost/mpl/apply_wrap.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
FMetafunction ClassA metafunction class to invoke.
A1,... AnAny typeInvocation arguments.
+
+
+

Expression semantics

+

For any Metafunction Class f and arbitrary types a1,... an:

+
+typedef apply_wrapn<f,a1,...an>::type t;
+
+ +++ + + + + + +
Return type:Any type.
Semantics:If n > 0, equivalent to typedef f::apply<a1,... an>::type t;, +otherwise equivalent to either typedef f::apply::type t; or +typedef f::apply<>::type t; depending on whether f::apply is +a class or a class template.
+
+
+

Example

+
+struct f0
+{
+    template< typename T = int > struct apply
+    {
+        typedef char type;
+    };
+};
+    
+struct g0
+{
+    struct apply { typedef char type; };
+};
+
+struct f2
+{
+    template< typename T1, typename T2 > struct apply
+    {
+        typedef T2 type;
+    };
+};
+
+
+typedef apply_wrap0< f0 >::type r1;
+typedef apply_wrap0< g0 >::type r2;
+typedef apply_wrap2< f2,int,char >::type r3;
+
+BOOST_MPL_ASSERT(( is_same<r1,char> ));
+BOOST_MPL_ASSERT(( is_same<r2,char> ));
+BOOST_MPL_ASSERT(( is_same<r3,char> ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/apply.html b/doc/refmanual/apply.html new file mode 100644 index 0000000..755ad01 --- /dev/null +++ b/doc/refmanual/apply.html @@ -0,0 +1,137 @@ + + + + + + +The MPL Reference Manual: apply + + + + + +
Front Page / Metafunctions / Invocation / apply
+
+

apply

+
+

Synopsis

+
+template< 
+      typename F
+    >
+struct apply0
+{
+    typedef unspecified type;
+};
+
+template< 
+      typename F, typename A1
+    >
+struct apply1
+{
+    typedef unspecified type;
+};
+
+...
+
+template< 
+      typename F, typename A1,... typename An
+    >
+struct applyn
+{
+    typedef unspecified type;
+};
+
+template< 
+      typename F
+    , typename A1 = unspecified
+    ...
+    , typename An = unspecified
+    >
+struct apply
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Invokes a Metafunction Class or a Lambda Expression F with arguments A1,... An.

+
+
+

Header

+
+#include <boost/mpl/apply.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
FLambda ExpressionAn expression to invoke.
A1,... AnAny typeInvocation arguments.
+
+
+

Expression semantics

+

For any Lambda Expression f and arbitrary types a1,... an:

+
+typedef applyn<f,a1,...an>::type t;
+typedef apply<f,a1,...an>::type t;
+
+ +++ + + + + + +
Return type:Any type.
Semantics:Equivalent to typedef apply_wrapn< lambda<f>::type,a1,... an>::type t;.
+
+
+

Example

+
+template< typename N1, typename N2 > struct int_plus
+    : int_<( N1::value + N2::value )>
+{
+};
+
+typedef apply< int_plus<_1,_2>, int_<2>, int_<3> >::type r1;
+typedef apply< quote2<int_plus>, int_<2>, int_<3> >::type r2;
+
+BOOST_MPL_ASSERT_RELATION( r1::value, ==, 5 );
+BOOST_MPL_ASSERT_RELATION( r2::value, ==, 5 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/arg.html b/doc/refmanual/arg.html new file mode 100644 index 0000000..3ab828c --- /dev/null +++ b/doc/refmanual/arg.html @@ -0,0 +1,113 @@ + + + + + + +The MPL Reference Manual: arg + + + + + +
Front Page / Metafunctions / Composition and Argument Binding / arg
+
+

arg

+
+

Synopsis

+
+template< int n > struct arg;
+
+template<> struct arg<1>
+{
+    template< typename A1,... typename An = unspecified >
+    struct apply
+    {
+        typedef A1 type;
+    };
+};
+
+...
+
+template<> struct arg<n>
+{
+    template< typename A1,... typename An >
+    struct apply
+    {
+        typedef An type;
+    };
+};
+
+
+
+

Description

+

arg<n> specialization is a Metafunction Class that return the nth of its arguments.

+
+
+

Header

+
+#include <boost/mpl/arg.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
nAn integral constantA number of argument to return.
+
+
+

Expression semantics

+

For any integral constant n in the range [1, BOOST_MPL_LIMIT_METAFUNCTION_ARITY] and +arbitrary types a1,... an:

+
+typedef apply_wrapn< arg<n>,a1,...an >::type x;
+
+ +++ + + + + + +
Return type:A type.
Semantics:x is identical to an.
+
+
+

Example

+
+typedef apply_wrap5< arg<1>,bool,char,short,int,long >::type t1;
+typedef apply_wrap5< arg<3>,bool,char,short,int,long >::type t3;
+
+BOOST_MPL_ASSERT(( is_same< t1, bool > ));
+BOOST_MPL_ASSERT(( is_same< t3, short > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/arithmetic-operations.html b/doc/refmanual/arithmetic-operations.html new file mode 100644 index 0000000..5945f74 --- /dev/null +++ b/doc/refmanual/arithmetic-operations.html @@ -0,0 +1,31 @@ + + + + + + +The MPL Reference Manual: Arithmetic Operations + + + + + +
Front Page / Metafunctions / Arithmetic Operations
+ + + + + + diff --git a/doc/refmanual/assert-msg.html b/doc/refmanual/assert-msg.html new file mode 100644 index 0000000..a63876f --- /dev/null +++ b/doc/refmanual/assert-msg.html @@ -0,0 +1,152 @@ + + + + + + +The MPL Reference Manual: BOOST_MPL_ASSERT_MSG + + + + + +
Front Page / Macros / Asserts / BOOST_MPL_ASSERT_MSG
+
+

BOOST_MPL_ASSERT_MSG

+
+

Synopsis

+
+#define BOOST_MPL_ASSERT_MSG( condition, message, types ) \
+    unspecified token sequence \
+/**/
+
+
+
+

Description

+

Generates a compilation error with an embedded custom message when the condition +doesn't hold.

+
+
+

Header

+
+#include <boost/mpl/assert.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
conditionAn integral constant expressionA condition to be asserted.
messageA legal identifier tokenA custom message in a form of a legal C++ +identifier token.
typesA legal function parameter listA parenthized list of types to be displayed +in the error message.
+
+
+

Expression semantics

+

For any integral constant expression expr, legal C++ identifier message, and +arbitrary types t1, t2,... tn:

+
+BOOST_MPL_ASSERT_MSG( expr, message, (t1, t2,... tn) );
+
+ +++ + + + + + + + +
Return type:None.
Precondition:t1, t2,... tn are non-void.
Semantics:

Generates a compilation error if expr::value != true, otherwise +has no effect.

+

When possible within the compiler's diagnostic capabilities, +the error message will include the message identifier and the parenthized +list of t1, t2,... tn types, and have a general form of:

+
+... ************( ...::message )************)(t1, t2,... tn) ...
+
+
+
+BOOST_MPL_ASSERT_MSG( expr, message, (types<t1, t2,... tn>) );
+
+ +++ + + + + + + + +
Return type:None.
Precondition:None.
Semantics:

Generates a compilation error if expr::value != true, otherwise +has no effect.

+

When possible within the compiler's diagnostics capabilities, +the error message will include the message identifier and the list of +t1, t2,... tn types, and have a general form of:

+
+... ************( ...::message )************)(types<t1, t2,... tn>) ...
+
+
+
+
+

Example

+
+template< typename T > struct my
+{
+    // ...
+    BOOST_MPL_ASSERT_MSG( 
+          is_integral<T>::value
+        , NON_INTEGRAL_TYPES_ARE_NOT_ALLOWED
+        , (T)
+        );
+};
+
+my<void*> test;
+
+// In instantiation of `my<void*>':
+//   instantiated from here
+// conversion from `
+//   mpl_::failed************(my<void*>::
+//   NON_INTEGRAL_TYPES_ARE_NOT_ALLOWED::************)(void*)
+//   ' to non-scalar type `mpl_::assert<false>' requested
+
+
+ +
+ + + + + diff --git a/doc/refmanual/assert-not.html b/doc/refmanual/assert-not.html new file mode 100644 index 0000000..dae6006 --- /dev/null +++ b/doc/refmanual/assert-not.html @@ -0,0 +1,111 @@ + + + + + + +The MPL Reference Manual: BOOST_MPL_ASSERT_NOT + + + + + +
Front Page / Macros / Asserts / BOOST_MPL_ASSERT_NOT
+
+

BOOST_MPL_ASSERT_NOT

+
+

Synopsis

+
+#define BOOST_MPL_ASSERT_NOT( pred ) \
+    unspecified token sequence \
+/**/
+
+
+
+

Description

+

Generates a compilation error when predicate holds true.

+
+
+

Header

+
+#include <boost/mpl/assert.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
predBoolean nullary MetafunctionA predicate to be asserted to be false.
+
+
+

Expression semantics

+

For any boolean nullary Metafunction pred:

+
+BOOST_MPL_ASSERT_NOT(( pred ));
+
+ +++ + + + + + +
Return type:None.
Semantics:

Generates a compilation error if pred::type::value != false, otherwise +has no effect. Note that double parentheses are required even if no commas +appear in the condition.

+

When possible within the compiler's diagnostic capabilities, +the error message will include the predicate's full type name, and have a +general form of:

+
+... ************boost::mpl::not_< pred >::************ ...
+
+
+
+
+

Example

+
+template< typename T, typename U > struct my
+{
+    // ...
+    BOOST_MPL_ASSERT_NOT(( is_same< T,U > ));
+};
+
+my<void,void> test;
+
+// In instantiation of `my<void, void>':
+//   instantiated from here
+// conversion from `
+//   mpl_::failed************boost::mpl::not_<boost::is_same<void, void> 
+//   >::************' to non-scalar type `mpl_::assert<false>' requested
+
+
+ +
+ + + + + diff --git a/doc/refmanual/assert-relation.html b/doc/refmanual/assert-relation.html new file mode 100644 index 0000000..da15b73 --- /dev/null +++ b/doc/refmanual/assert-relation.html @@ -0,0 +1,120 @@ + + + + + + +The MPL Reference Manual: BOOST_MPL_ASSERT_RELATION + + + + + +
Front Page / Macros / Asserts / BOOST_MPL_ASSERT_RELATION
+
+

BOOST_MPL_ASSERT_RELATION

+
+

Synopsis

+
+#define BOOST_MPL_ASSERT_RELATION( x, relation, y ) \
+    unspecified token sequence \
+/**/
+
+
+
+

Description

+

A specialized assertion macro for checking numerical conditions. Generates +a compilation error when the condition ( x relation y ) +doesn't hold.

+
+
+

Header

+
+#include <boost/mpl/assert.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
xAn integral constantLeft operand of the checked relation.
yAn integral constantRight operand of the checked relation.
relationA C++ operator tokenAn operator token for the relation being +checked.
+
+
+

Expression semantics

+

For any integral constants x, y and a legal C++ operator token op:

+
+BOOST_MPL_ASSERT_RELATION( x, op, y );
+
+ +++ + + + + + +
Return type:None.
Semantics:

Generates a compilation error if ( x op y ) != true, otherwise +has no effect.

+

When possible within the compiler's diagnostic capabilities, +the error message will include a name of the relation being checked, +the actual values of both operands, and have a general form of:

+
+... ************...assert_relation<op, x, y>::************) ...
+
+
+
+
+

Example

+
+template< typename T, typename U > struct my
+{
+    // ...
+    BOOST_MPL_ASSERT_RELATION( sizeof(T), <, sizeof(U) );
+};
+
+my<char[50],char[10]> test;
+
+// In instantiation of `my<char[50], char[10]>':
+//   instantiated from here
+// conversion from `
+//   mpl_::failed************mpl_::assert_relation<less, 50, 10>::************' 
+//   to non-scalar type `mpl_::assert<false>' requested
+
+
+ +
+ + + + + diff --git a/doc/refmanual/assert.html b/doc/refmanual/assert.html new file mode 100644 index 0000000..6dd79a6 --- /dev/null +++ b/doc/refmanual/assert.html @@ -0,0 +1,111 @@ + + + + + + +The MPL Reference Manual: BOOST_MPL_ASSERT + + + + + +
Front Page / Macros / Asserts / BOOST_MPL_ASSERT
+
+

BOOST_MPL_ASSERT

+
+

Synopsis

+
+#define BOOST_MPL_ASSERT( pred ) \
+    unspecified token sequence \
+/**/
+
+
+
+

Description

+

Generates a compilation error when the predicate pred holds false.

+
+
+

Header

+
+#include <boost/mpl/assert.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
predBoolean nullary MetafunctionA predicate to be asserted.
+
+
+

Expression semantics

+

For any boolean nullary Metafunction pred:

+
+BOOST_MPL_ASSERT(( pred ));
+
+ +++ + + + + + +
Return type:None.
Semantics:

Generates a compilation error if pred::type::value != true, otherwise +has no effect. Note that double parentheses are required even if no commas +appear in the condition.

+

When possible within the compiler's diagnostic capabilities, +the error message will include the predicate's full type name, and have a +general form of:

+
+... ************ pred::************ ...
+
+
+
+
+

Example

+
+template< typename T, typename U > struct my
+{
+    // ...
+    BOOST_MPL_ASSERT(( is_same< T,U > ));
+};
+
+my<void*,char*> test;
+
+// In instantiation of `my<void, char*>':
+//   instantiated from here
+// conversion from `
+//   mpl_::failed************boost::is_same<void, char*>::************' to 
+//   non-scalar type `mpl_::assert<false>' requested
+
+
+ +
+ + + + + diff --git a/doc/refmanual/asserts.html b/doc/refmanual/asserts.html new file mode 100644 index 0000000..5bf26e8 --- /dev/null +++ b/doc/refmanual/asserts.html @@ -0,0 +1,33 @@ + + + + + + +The MPL Reference Manual: Asserts + + + + + +
Front Page / Macros / Asserts
+
+

Asserts

+

The MPL supplies a suite of static assertion macros that are specifically +designed to generate maximally useful and informative error messages +within the diagnostic capabilities of each compiler.

+

All assert macros can be used at class, function, or namespace scope.

+ + + +
+ + + + + diff --git a/doc/refmanual/associative-sequence.html b/doc/refmanual/associative-sequence.html new file mode 100644 index 0000000..aa8f1ea --- /dev/null +++ b/doc/refmanual/associative-sequence.html @@ -0,0 +1,156 @@ + + + + + + +The MPL Reference Manual: Associative Sequence + + + + + +
Front Page / Sequences / Concepts / Associative Sequence
+
+

Associative Sequence

+
+

Description

+

An Associative Sequence is a Forward Sequence that allows efficient retrieval of +elements based on keys. Unlike associative containers in the C++ Standard Library, +MPL associative sequences have no associated ordering relation. Instead, +type identity is used to impose an equivalence relation on keys, and the +order in which sequence elements are traversed during iteration is left +unspecified.

+
+
+

Definitions

+
    +
  • A key is a part of the element type used to identify and retrieve +the element within the sequence.
  • +
  • A value is a part of the element type retrievied from the sequence +by its key.
  • +
+
+
+

Expression requirements

+

In the following table and subsequent specifications, s is an Associative Sequence, +x is a sequence element, and k and def are arbitrary types.

+

In addition to the requirements defined in Forward Sequence, +the following must be met:

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionTypeComplexity
has_key<s,k>::typeBoolean Integral ConstantAmortized constant time
count<s,k>::typeIntegral ConstantAmortized constant time
order<s,k>::typeIntegral Constant or void_Amortized constant time
at<s,k>::typeAny typeAmortized constant time
at<s,k,def>::typeAny typeAmortized constant time
key_type<s,x>::typeAny typeAmortized constant time
value_type<s,x>::typeAny typeAmortized constant time
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Forward Sequence.

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionSemantics
has_key<s,k>::typeA boolean Integral Constant c such that +c::value == true if and only if there is one or more +elements with the key k in s; see has_key.
count<s,k>::typeThe number of elements with the key k in s; +see count.
order<s,k>::typeA unique unsigned Integral Constant associated +with the key k in the sequence s; see order.
+at<s,k>::type
+at<s,k,def>::type
+
+
The first element associated with the key k +in the sequence s; see at.
key_type<s,x>::typeThe key part of the element x that would be +used to identify x in s; see key_type.
value_type<s,x>::typeThe value part of the element x that would be +used for x in s; see value_type.
+ +
+
+

Models

+ + +
+ +
+ + + + + diff --git a/doc/refmanual/at-c.html b/doc/refmanual/at-c.html new file mode 100644 index 0000000..1a339ca --- /dev/null +++ b/doc/refmanual/at-c.html @@ -0,0 +1,132 @@ + + + + + + +The MPL Reference Manual: at_c + + + + + +
Front Page / Sequences / Intrinsic Metafunctions / at_c
+
+

at_c

+
+

Synopsis

+
+template<
+      typename Sequence
+    , long n
+    >
+struct at_c
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a type identical to the nth element from the beginning of +the sequence. at_c<Sequence,n>::type is a shorcut notation for +at< Sequence, long_<n> >::type.

+
+
+

Header

+
+#include <boost/mpl/at.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceA sequence to be examined.
nA compile-time integral constantAn offset from the beginning of the sequence +specifying the element to be retrieved.
+
+
+

Expression semantics

+
+typedef at_c<Sequence,n>::type t; 
+
+ +++ + + + + + + + +
Return type:A type
Precondition:0 <= n < size<Sequence>::value
Semantics:

Equivalent to

+
+typedef at< Sequence, long_<n> >::type t;
+
+
+
+
+

Complexity

+ ++++ + + + + + + + + + + + + + +
Sequence archetypeComplexity
Forward SequenceLinear.
Random Access SequenceAmortized constant time.
+
+
+

Example

+
+typedef range_c<long,10,50> range;
+BOOST_MPL_ASSERT_RELATION( (at_c< range,0 >::value), ==, 10 );
+BOOST_MPL_ASSERT_RELATION( (at_c< range,10 >::value), ==, 20 );
+BOOST_MPL_ASSERT_RELATION( (at_c< range,40 >::value), ==, 50 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/at.html b/doc/refmanual/at.html new file mode 100644 index 0000000..1be8132 --- /dev/null +++ b/doc/refmanual/at.html @@ -0,0 +1,211 @@ + + + + + + +The MPL Reference Manual: at + + + + + +
Front Page / Sequences / Intrinsic Metafunctions / at
+
+

at

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename N
+    >
+struct at
+{
+    typedef unspecified type;
+};
+
+template<
+      typename AssocSeq
+    , typename Key
+    , typename Default = unspecified
+    >
+struct at
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

at is an overloaded name:

+
    +
  • at<Sequence,N> returns the N-th element from the beginning of the +Forward Sequence Sequence.
  • +
  • at<AssocSeq,Key,Default> returns the first element associated with Key +in the Associative Sequence AssocSeq, or Default if no such element +exists.
  • +
+
+
+

Header

+
+#include <boost/mpl/at.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceA sequence to be examined.
AssocSeqAssociative SequenceA sequence to be examined.
NIntegral ConstantAn offset from the beginning of the sequence +specifying the element to be retrieved.
KeyAny typeA key for the element to be retrieved.
DefaultAny typeA default value to return if the element is +not found.
+
+
+

Expression semantics

+
+

For any Forward Sequence s, and Integral Constant n:

+
+typedef at<s,n>::type t; 
+
+ +++ + + + + + + + +
Return type:A type.
Precondition:0 <= n::value < size<s>::value.
Semantics:

Equivalent to

+
+typedef deref< advance< begin<s>::type,n >::type >::type t;
+
+
+
+
+

For any Associative Sequence s, and arbitrary types key and x:

+
+typedef at<s,key,x>::type t; 
+
+ +++ + + + + + +
Return type:A type.
Semantics:If has_key<s,key>::value == true, t is the value type associated with key; +otherwise t is identical to x.
+ +
+typedef at<s,key>::type t; 
+
+ +++ + + + + + +
Return type:A type.
Semantics:

Equivalent to

+
+typedef at<s,key,void_>::type t;
+
+
+
+
+
+

Complexity

+ ++++ + + + + + + + + + + + + + + + + +
Sequence archetypeComplexity
Forward SequenceLinear.
Random Access SequenceAmortized constant time.
Associative SequenceAmortized constant time.
+
+
+

Example

+
+typedef range_c<long,10,50> range;
+BOOST_MPL_ASSERT_RELATION( (at< range, int_<0> >::value), ==, 10 );
+BOOST_MPL_ASSERT_RELATION( (at< range, int_<10> >::value), ==, 20 );
+BOOST_MPL_ASSERT_RELATION( (at< range, int_<40> >::value), ==, 50 );
+
+
+typedef set< int const,long*,double > s;
+
+BOOST_MPL_ASSERT(( is_same< at<s,char>::type, void_ > ));
+BOOST_MPL_ASSERT(( is_same< at<s,int>::type, int > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/aux-lambda-support.html b/doc/refmanual/aux-lambda-support.html new file mode 100644 index 0000000..413e979 --- /dev/null +++ b/doc/refmanual/aux-lambda-support.html @@ -0,0 +1,120 @@ + + + + + + +The MPL Reference Manual: BOOST_MPL_AUX_LAMBDA_SUPPORT + + + + + +
Front Page / Macros / Broken Compiler Workarounds / BOOST_MPL_AUX_LAMBDA_SUPPORT
+
+

BOOST_MPL_AUX_LAMBDA_SUPPORT

+
+

Synopsis

+
+#define BOOST_MPL_AUX_LAMBDA_SUPPORT(arity, fun, params) \
+    unspecified token sequence \
+/**/
+
+
+
+

Description

+

Enables metafunction fun for the use in Lambda Expressions on +compilers that don't support partial template specialization or/and +template template parameters. Expands to nothing on conforming compilers.

+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
arityAn integral constantThe metafunction's arity, i.e. the number of its +template parameters, including the defaults.
funA legal identifier tokenThe metafunction's name.
paramsA PP-tupleA tuple of the metafunction's parameter names, in +their original order, including the defaults.
+
+
+

Expression semantics

+

For any integral constant n, a Metafunction fun, and arbitrary types A1,... An:

+
+template< typename A1,... typename An > struct fun
+{
+    // ...
+
+    BOOST_MPL_AUX_LAMBDA_SUPPORT(n, fun, (A1,...An))
+};
+
+ +++ + + + + + + + +
Precondition:Appears in fun's scope, immediately followed by the scope-closing +bracket (}).
Return type:None.
Semantics:Expands to nothing and has no effect on conforming compilers. On compilers that +don't support partial template specialization or/and template template parameters +expands to an unspecified token sequence enabling fun to participate in +Lambda Expressions with the semantics described in this manual.
+
+
+

Example

+
+template< typename T, typename U = int > struct f
+{
+    typedef T type[sizeof(U)];
+
+    BOOST_MPL_AUX_LAMBDA_SUPPORT(2, f, (T,U))
+};
+
+typedef apply1< f<char,_1>,long >::type r;
+BOOST_MPL_ASSERT(( is_same< r, char[sizeof(long)] > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/back-extensible-sequence.html b/doc/refmanual/back-extensible-sequence.html new file mode 100644 index 0000000..0de8463 --- /dev/null +++ b/doc/refmanual/back-extensible-sequence.html @@ -0,0 +1,104 @@ + + + + + + +The MPL Reference Manual: Back Extensible Sequence + + + + + +
Front Page / Sequences / Concepts / Back Extensible Sequence
+
+

Back Extensible Sequence

+
+

Description

+

A Back Extensible Sequence is an Extensible Sequence that supports amortized constant +time insertion and removal operations at the end.

+
+ +
+

Expression requirements

+

In addition to the requirements defined in Extensible Sequence, +for any Back Extensible Sequence s the following must be met:

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ExpressionTypeComplexity
push_back<s,x>::typeBack Extensible SequenceAmortized constant time
pop_back<s>::typeBack Extensible SequenceAmortized constant time
back<s>::typeAny typeAmortized constant time
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Extensible Sequence.

+ ++++ + + + + + + + + + + + + + + + + +
ExpressionSemantics
push_back<s,x>::typeEquivalent to insert<s,end<s>::type,x>::type; +see push_back.
pop_back<v>::typeEquivalent to erase<s,end<s>::type>::type; +see pop_back.
back<s>::typeThe last element in the sequence; see back.
+
+
+

Models

+ +
+ +
+ + + + + diff --git a/doc/refmanual/back-inserter.html b/doc/refmanual/back-inserter.html new file mode 100644 index 0000000..f0137cd --- /dev/null +++ b/doc/refmanual/back-inserter.html @@ -0,0 +1,117 @@ + + + + + + +The MPL Reference Manual: back_inserter + + + + + +
Front Page / Algorithms / Inserters / back_inserter
+
+

back_inserter

+
+

Synopsis

+
+template<
+      typename Seq
+    >
+struct back_inserter
+{
+    // unspecified
+    // ...
+};
+
+
+
+

Description

+

Inserts elements at the end of the sequence.

+
+ + +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
SeqBack Extensible SequenceA sequence to bind the inserter to.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Inserter.

+

For any Back Extensible Sequence s:

+ ++++ + + + + + + + + + + +
ExpressionSemantics
back_inserter<s>

An Inserter in, equivalent to

+
+struct in : inserter<s,push_back<_1,_2> > {};
+
+
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef copy<
+      range_c<int,5,10>
+    , back_inserter< vector_c<int,0,1,2,3,4> >
+    >::type range;
+   
+BOOST_MPL_ASSERT(( equal< range, range_c<int,0,10> > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/back.html b/doc/refmanual/back.html new file mode 100644 index 0000000..95287a8 --- /dev/null +++ b/doc/refmanual/back.html @@ -0,0 +1,114 @@ + + + + + + +The MPL Reference Manual: back + + + + + +
Front Page / Sequences / Intrinsic Metafunctions / back
+
+

back

+
+

Synopsis

+
+template<
+      typename Sequence
+    >
+struct back
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the last element in the sequence.

+
+
+

Header

+
+#include <boost/mpl/back.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceBidirectional SequenceA sequence to be examined.
+
+
+

Expression semantics

+

For any Bidirectional Sequence s:

+
+typedef back<s>::type t; 
+
+ +++ + + + + + + + +
Return type:A type.
Precondition:empty<s>::value == false.
Semantics:

Equivalent to

+
+typedef deref< prior< end<s>::type >::type >::type t;
+
+
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef range_c<int,0,1> range1;
+typedef range_c<int,0,10> range2;
+typedef range_c<int,-10,0> range3;
+    
+BOOST_MPL_ASSERT_RELATION( back<range1>::value, ==, 0 );
+BOOST_MPL_ASSERT_RELATION( back<range2>::value, ==, 9 );
+BOOST_MPL_ASSERT_RELATION( back<range3>::value, ==, -1 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/begin.html b/doc/refmanual/begin.html new file mode 100644 index 0000000..f989262 --- /dev/null +++ b/doc/refmanual/begin.html @@ -0,0 +1,114 @@ + + + + + + +The MPL Reference Manual: begin + + + + + +
Front Page / Sequences / Intrinsic Metafunctions / begin
+
+

begin

+
+

Synopsis

+
+template<
+      typename X
+    >
+struct begin
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns an iterator that points to the first element of the sequence. If +the argument is not a Forward Sequence, returns void_.

+
+
+

Header

+
+#include <boost/mpl/begin_end.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
XAny typeA type whose begin iterator, if any, will be +returned.
+
+
+

Expression semantics

+

For any arbitrary type x:

+
+typedef begin<x>::type first;
+
+ +++ + + + + + + + +
Return type:Forward Iterator or void_.
Semantics:If x is a Forward Sequence, first is an iterator pointing to the +first element of s; otherwise first is void_.
Postcondition:If first is an iterator, it is either dereferenceable or past-the-end; it +is past-the-end if and only if size<x>::value == 0.
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef vector< unsigned char,unsigned short,
+    unsigned int,unsigned long > unsigned_types;
+
+typedef begin<unsigned_types>::type iter;
+BOOST_MPL_ASSERT(( is_same< deref<iter>::type, unsigned char > ));
+
+BOOST_MPL_ASSERT(( is_same< begin<int>::type, void_ > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/bidirectional-iterator.html b/doc/refmanual/bidirectional-iterator.html new file mode 100644 index 0000000..cc12165 --- /dev/null +++ b/doc/refmanual/bidirectional-iterator.html @@ -0,0 +1,107 @@ + + + + + + +The MPL Reference Manual: Bidirectional Iterator + + + + + +
Front Page / Iterators / Concepts / Bidirectional Iterator
+
+

Bidirectional Iterator

+
+

Description

+

A Bidirectional Iterator is a Forward Iterator that provides a way to +obtain an iterator to the previous element in a sequence.

+
+ +
+

Definitions

+
    +
  • a bidirectional iterator i is decrementable if there is a "previous" +iterator, that is, if prior<i>::type expression is well-defined; +iterators pointing to the first element of the sequence are not +decrementable.
  • +
+
+
+

Expression requirements

+

In addition to the requirements defined in Forward Iterator, +the following requirements must be met.

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ExpressionTypeComplexity
next<i>::typeBidirectional IteratorAmortized constant time
prior<i>::typeBidirectional IteratorAmortized constant time
i::categoryIntegral Constant, convertible +to bidirectional_iterator_tagConstant time
+
+
+

Expression semantics

+
+typedef prior<i>::type j;
+
+ +++ + + + + + + + +
Precondition:i is decrementable
Semantics:j is an iterator pointing to the previous element of the +sequence
Postcondition:j is dereferenceable and incrementable
+
+
+

Invariants

+

For any bidirectional iterators i and j the following invariants +always hold:

+
    +
  • If i is incrementable, then prior< next<i>::type >::type is a null +operation; similarly, if i is decrementable, next< prior<i>::type >::type +is a null operation.
  • +
+
+ +
+ + + + + diff --git a/doc/refmanual/bidirectional-sequence.html b/doc/refmanual/bidirectional-sequence.html new file mode 100644 index 0000000..ca7c5ae --- /dev/null +++ b/doc/refmanual/bidirectional-sequence.html @@ -0,0 +1,96 @@ + + + + + + +The MPL Reference Manual: Bidirectional Sequence + + + + + +
Front Page / Sequences / Concepts / Bidirectional Sequence
+
+

Bidirectional Sequence

+ + +
+

Expression requirements

+

In addition to the requirements defined in Forward Sequence, +for any Bidirectional Sequence s the following must be met:

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ExpressionTypeComplexity
begin<s>::typeBidirectional IteratorAmortized constant time
end<s>::typeBidirectional IteratorAmortized constant time
back<s>::typeAny typeAmortized constant time
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Forward Sequence.

+ ++++ + + + + + + + + + + +
ExpressionSemantics
back<s>::typeThe last element in the sequence; see back.
+
+ + +
+ + + + + diff --git a/doc/refmanual/bind.html b/doc/refmanual/bind.html new file mode 100644 index 0000000..8bf8685 --- /dev/null +++ b/doc/refmanual/bind.html @@ -0,0 +1,224 @@ + + + + + + +The MPL Reference Manual: bind + + + + + +
Front Page / Metafunctions / Composition and Argument Binding / bind
+
+

bind

+
+

Synopsis

+
+template< 
+      typename F
+    >
+struct bind0
+{
+    // unspecified
+    // ...
+};
+
+template< 
+      typename F, typename A1
+    >
+struct bind1
+{
+    // unspecified
+    // ...
+};
+
+...
+
+template< 
+      typename F, typename A1,... typename An
+    >
+struct bindn
+{
+    // unspecified
+    // ...
+};
+
+template< 
+      typename F
+    , typename A1 = unspecified
+    ...
+    , typename An = unspecified
+    >
+struct bind
+{
+    // unspecified
+    // ...
+};
+
+
+
+

Description

+

bind is a higher-order primitive for Metafunction Class composition +and argument binding. In essence, it's a compile-time counterpart of +the similar run-time functionality provided by Boost.Bind and Boost.Lambda +libraries.

+
+
+

Header

+
+#include <boost/mpl/bind.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
FMetafunction ClassAn metafunction class to perform binding on.
A1,... AnAny typeArguments to bind.
+
+
+

Expression semantics

+

For any Metafunction Class f and arbitrary types a1,... an:

+
+typedef bind<f,a1,...an> g;
+typedef bindn<f,a1,...an> g;
+
+ +++ + + + +
Return type:Metafunction Class
+ +++ + + + +
Semantics:

Equivalent to

+
+struct g
+{
+    template< 
+          typename U1 = unspecified
+        ...
+        , typename Un = unspecified
+        >
+    struct apply
+        : apply_wrapn<
+              typename h0<f,U1,...Un>::type 
+            , typename h1<a1,U1,...Un>::type 
+            ...
+            , typename hn<an,U1,...Un>::type 
+            >
+    {
+    };
+};
+
+

where hk is equivalent to

+
+template< typename X, typename U1,... typename Un > struct hk
+    : apply_wrapn<X,U1,...Un>
+{
+};
+
+

if f or ak is a bind expression or a placeholder, and

+
+template< typename X, typename U1,... typename Un > struct hk
+{
+    typedef X type;
+};
+
+

otherwise. [Note: Every nth appearance of the unnamed placeholder +in the bind<f,a1,...an> specialization is replaced with the corresponding +numbered placeholder _n — end note]

+
+
+
+

Example

+
+struct f1
+{
+    template< typename T1 > struct apply
+    {
+        typedef T1 type;
+    };
+};
+
+struct f5
+{
+    template< typename T1, typename T2, typename T3, typename T4, typename T5 >
+    struct apply
+    {
+        typedef T5 type;
+    };
+};
+
+typedef apply_wrap1< 
+      bind1<f1,_1>
+    , int 
+    >::type r11;
+
+typedef apply_wrap5< 
+      bind1<f1,_5>
+    , void,void,void,void,int 
+    >::type r12;
+
+BOOST_MPL_ASSERT(( is_same<r11,int> ));
+BOOST_MPL_ASSERT(( is_same<r12,int> ));
+
+typedef apply_wrap5< 
+      bind5<f5,_1,_2,_3,_4,_5>
+    , void,void,void,void,int 
+    >::type r51;
+
+typedef apply_wrap5<
+      bind5<f5,_5,_4,_3,_2,_1>
+    , int,void,void,void,void
+    >::type r52;
+
+BOOST_MPL_ASSERT(( is_same<r51,int> ));
+BOOST_MPL_ASSERT(( is_same<r52,int> ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/bitand.html b/doc/refmanual/bitand.html new file mode 100644 index 0000000..ec8975f --- /dev/null +++ b/doc/refmanual/bitand.html @@ -0,0 +1,149 @@ + + + + + + +The MPL Reference Manual: bitand_ + + + + + +
Front Page / Metafunctions / Bitwise Operations / bitand_
+
+

bitand_

+
+

Synopsis

+
+template<
+      typename T1
+    , typename T2
+    , typename T3 = unspecified
+    ...
+    , typename Tn = unspecified
+    >
+struct bitand_
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the result of bitwise and (&) operation of its arguments.

+
+
+

Header

+
+#include <boost/mpl/bitand.hpp>
+#include <boost/mpl/bitwise.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
T1, T2,... TnIntegral ConstantOperation's arguments.
+

[Note: The requirements listed in this specification +are the ones imposed by the default implementation. See Numeric Metafunction concept +for the details on how to provide an implementation for a user-defined numeric type +that does not satisfy the Integral Constant requirements. — end note]

+
+
+

Expression semantics

+

For any Integral Constants c1,c2,... cn:

+
+typedef bitand_<c1,...cn>::type r; 
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+typedef integral_c<
+      typeof(c1::value & c2::value)
+    , ( c1::value & c2::value )
+    > c;
+    
+typedef bitand_<c,c3,...cn>::type r; 
+
+
+ +
+typedef bitand_<c1,...cn> r;
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+struct r : bitand_<c1,...cn>::type {};
+
+
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef integral_c<unsigned,0> u0;
+typedef integral_c<unsigned,1> u1;
+typedef integral_c<unsigned,2> u2;
+typedef integral_c<unsigned,8> u8;
+typedef integral_c<unsigned,0xffffffff> uffffffff;
+
+BOOST_MPL_ASSERT_RELATION( (bitand_<u0,u0>::value), ==, 0 );
+BOOST_MPL_ASSERT_RELATION( (bitand_<u1,u0>::value), ==, 0 );
+BOOST_MPL_ASSERT_RELATION( (bitand_<u0,u1>::value), ==, 0 );
+BOOST_MPL_ASSERT_RELATION( (bitand_<u0,uffffffff>::value), ==, 0 );
+BOOST_MPL_ASSERT_RELATION( (bitand_<u1,uffffffff>::value), ==, 1 );
+BOOST_MPL_ASSERT_RELATION( (bitand_<u8,uffffffff>::value), ==, 8 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/bitor.html b/doc/refmanual/bitor.html new file mode 100644 index 0000000..3bf306a --- /dev/null +++ b/doc/refmanual/bitor.html @@ -0,0 +1,149 @@ + + + + + + +The MPL Reference Manual: bitor_ + + + + + +
Front Page / Metafunctions / Bitwise Operations / bitor_
+
+

bitor_

+
+

Synopsis

+
+template<
+      typename T1
+    , typename T2
+    , typename T3 = unspecified
+    ...
+    , typename Tn = unspecified
+    >
+struct bitor_
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the result of bitwise or (|) operation of its arguments.

+
+
+

Header

+
+#include <boost/mpl/bitor.hpp>
+#include <boost/mpl/bitwise.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
T1, T2,... TnIntegral ConstantOperation's arguments.
+

[Note: The requirements listed in this specification +are the ones imposed by the default implementation. See Numeric Metafunction concept +for the details on how to provide an implementation for a user-defined numeric type +that does not satisfy the Integral Constant requirements. — end note]

+
+
+

Expression semantics

+

For any Integral Constants c1,c2,... cn:

+
+typedef bitor_<c1,...cn>::type r; 
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+typedef integral_c<
+      typeof(c1::value | c2::value)
+    , ( c1::value | c2::value )
+    > c;
+    
+typedef bitor_<c,c3,...cn>::type r; 
+
+
+ +
+typedef bitor_<c1,...cn> r;
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+struct r : bitor_<c1,...cn>::type {};
+
+
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef integral_c<unsigned,0> u0;
+typedef integral_c<unsigned,1> u1;
+typedef integral_c<unsigned,2> u2;
+typedef integral_c<unsigned,8> u8;
+typedef integral_c<unsigned,0xffffffff> uffffffff;
+
+BOOST_MPL_ASSERT_RELATION( (bitor_<u0,u0>::value), ==, 0 );
+BOOST_MPL_ASSERT_RELATION( (bitor_<u1,u0>::value), ==, 1 );
+BOOST_MPL_ASSERT_RELATION( (bitor_<u0,u1>::value), ==, 1 );
+BOOST_MPL_ASSERT_RELATION( (bitor_<u0,uffffffff>::value), ==, 0xffffffff );
+BOOST_MPL_ASSERT_RELATION( (bitor_<u1,uffffffff>::value), ==, 0xffffffff );
+BOOST_MPL_ASSERT_RELATION( (bitor_<u8,uffffffff>::value), ==, 0xffffffff );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/bitwise-operations.html b/doc/refmanual/bitwise-operations.html new file mode 100644 index 0000000..9c17f54 --- /dev/null +++ b/doc/refmanual/bitwise-operations.html @@ -0,0 +1,30 @@ + + + + + + +The MPL Reference Manual: Bitwise Operations + + + + + +
Front Page / Metafunctions / Bitwise Operations
+ + + + + + diff --git a/doc/refmanual/bitxor.html b/doc/refmanual/bitxor.html new file mode 100644 index 0000000..baa7a73 --- /dev/null +++ b/doc/refmanual/bitxor.html @@ -0,0 +1,150 @@ + + + + + + +The MPL Reference Manual: bitxor_ + + + + + +
Front Page / Metafunctions / Bitwise Operations / bitxor_
+
+

bitxor_

+
+

Synopsis

+
+template<
+      typename T1
+    , typename T2
+    , typename T3 = unspecified
+    ...
+    , typename Tn = unspecified
+    >
+struct bitxor_
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the result of bitwise xor (^) operation of its arguments.

+
+
+

Header

+
+#include <boost/mpl/bitxor.hpp>
+#include <boost/mpl/bitwise.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
T1, T2,... TnIntegral ConstantOperation's arguments.
+

[Note: The requirements listed in this specification +are the ones imposed by the default implementation. See Numeric Metafunction concept +for the details on how to provide an implementation for a user-defined numeric type +that does not satisfy the Integral Constant requirements. — end note]

+
+
+

Expression semantics

+

For any Integral Constants c1,c2,... cn:

+
+typedef bitxor_<c1,...cn>::type r; 
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+typedef integral_c<
+      typeof(c1::value ^ c2::value)
+    , ( c1::value ^ c2::value )
+    > c;
+    
+typedef bitxor_<c,c3,...cn>::type r; 
+
+
+ +
+typedef bitxor_<c1,...cn> r;
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+struct r : bitxor_<c1,...cn>::type {};
+
+
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef integral_c<unsigned,0> u0;
+typedef integral_c<unsigned,1> u1;
+typedef integral_c<unsigned,2> u2;
+typedef integral_c<unsigned,8> u8;
+typedef integral_c<unsigned,0xffffffff> uffffffff;
+
+BOOST_MPL_ASSERT_RELATION( (bitxor_<u0,u0>::value), ==, 0 );
+BOOST_MPL_ASSERT_RELATION( (bitxor_<u1,u0>::value), ==, 1 );
+BOOST_MPL_ASSERT_RELATION( (bitxor_<u0,u1>::value), ==, 1 );
+
+BOOST_MPL_ASSERT_RELATION( (bitxor_<u0,uffffffff>::value), ==, 0xffffffff ^ 0 );
+BOOST_MPL_ASSERT_RELATION( (bitxor_<u1,uffffffff>::value), ==, 0xffffffff ^ 1 );
+BOOST_MPL_ASSERT_RELATION( (bitxor_<u8,uffffffff>::value), ==, 0xffffffff ^ 8 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/bool.html b/doc/refmanual/bool.html new file mode 100644 index 0000000..36ecac8 --- /dev/null +++ b/doc/refmanual/bool.html @@ -0,0 +1,112 @@ + + + + + + +The MPL Reference Manual: bool_ + + + + + +
Front Page / Data Types / Numeric / bool_
+
+

bool_

+
+

Synopsis

+
+template<
+      bool C
+    >
+struct bool_
+{
+    // unspecified
+    // ...
+};
+
+typedef bool_<true>  true_;
+typedef bool_<false> false_;
+
+
+
+

Description

+

A boolean Integral Constant wrapper.

+
+
+

Header

+
+#include <boost/mpl/bool.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
CA boolean integral constantA value to wrap.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Integral Constant.

+

For arbitrary integral constant c:

+ ++++ + + + + + + + + + + +
ExpressionSemantics
bool_<c>An Integral Constant x such that x::value == c +and x::value_type is identical to bool.
+
+
+

Example

+
+BOOST_MPL_ASSERT(( is_same< bool_<true>::value_type, bool > ));
+BOOST_MPL_ASSERT(( is_same< bool_<true>, true_ > )); }
+BOOST_MPL_ASSERT(( is_same< bool_<true>::type, bool_<true> > ));
+BOOST_MPL_ASSERT_RELATION( bool_<true>::value, ==, true );
+assert( bool_<true>() == true );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/broken-compiler.html b/doc/refmanual/broken-compiler.html new file mode 100644 index 0000000..dd53ef9 --- /dev/null +++ b/doc/refmanual/broken-compiler.html @@ -0,0 +1,25 @@ + + + + + + +The MPL Reference Manual: Broken Compiler Workarounds + + + + + +
Front Page / Macros / Broken Compiler Workarounds
+ + + + + + diff --git a/doc/refmanual/categorized-concepts.html b/doc/refmanual/categorized-concepts.html new file mode 100644 index 0000000..371ee72 --- /dev/null +++ b/doc/refmanual/categorized-concepts.html @@ -0,0 +1,46 @@ + + + + + + +The MPL Reference Manual: Concepts + + + + + +
Front Page / Categorized Index / Concepts
+ + + + + + diff --git a/doc/refmanual/categorized-index.html b/doc/refmanual/categorized-index.html new file mode 100644 index 0000000..9dc77ee --- /dev/null +++ b/doc/refmanual/categorized-index.html @@ -0,0 +1,25 @@ + + + + + + +The MPL Reference Manual: Categorized Index + + + + + +
Front Page / Categorized Index
+ + + + + + diff --git a/doc/refmanual/cfg-no-has-xxx.html b/doc/refmanual/cfg-no-has-xxx.html new file mode 100644 index 0000000..0770149 --- /dev/null +++ b/doc/refmanual/cfg-no-has-xxx.html @@ -0,0 +1,40 @@ + + + + + + +The MPL Reference Manual: BOOST_MPL_CFG_NO_HAS_XXX + + + + + +
Front Page / Macros / Configuration / BOOST_MPL_CFG_NO_HAS_XXX
+
+

BOOST_MPL_CFG_NO_HAS_XXX

+ +
+

Description

+

BOOST_MPL_CFG_NO_HAS_XXX is an boolean configuration macro +signaling availability of the BOOST_MPL_HAS_XXX_TRAIT_DEF / +BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF introspection macros' functionality +on a particular compiler.

+
+ +
+ + + + + diff --git a/doc/refmanual/cfg-no-preprocessed.html b/doc/refmanual/cfg-no-preprocessed.html new file mode 100644 index 0000000..5c30190 --- /dev/null +++ b/doc/refmanual/cfg-no-preprocessed.html @@ -0,0 +1,46 @@ + + + + + + +The MPL Reference Manual: BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS + + + + + +
Front Page / Macros / Configuration / BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+
+

BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS

+ +
+

Description

+

BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS is an boolean configuration macro +regulating library's internal use of preprocessed headers. When defined, it +instructs the MPL to discard the pre-generated headers found in +boost/mpl/aux_/preprocessed directory and use preprocessor +metaprogramming techniques to generate the necessary versions of the +library components on the fly.

+

In this implementation of the library, the macro is not defined by default. +To change the default configuration, define +BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS before including any library +header.

+
+ +
+ + + + + diff --git a/doc/refmanual/classes.html b/doc/refmanual/classes.html new file mode 100644 index 0000000..d48e68b --- /dev/null +++ b/doc/refmanual/classes.html @@ -0,0 +1,38 @@ + + + + + + +The MPL Reference Manual: Classes + + + + + +
Front Page / Sequences / Classes
+
+

Classes

+

The MPL provides a large number of predefined general-purpose sequence +classes covering most of the typical metaprogramming needs out-of-box.

+ + + + +
+ + + + + diff --git a/doc/refmanual/clear.html b/doc/refmanual/clear.html new file mode 100644 index 0000000..1fbe149 --- /dev/null +++ b/doc/refmanual/clear.html @@ -0,0 +1,112 @@ + + + + + + +The MPL Reference Manual: clear + + + + + +
Front Page / Sequences / Intrinsic Metafunctions / clear
+
+

clear

+
+

Synopsis

+
+template<
+      typename Sequence
+    >
+struct clear
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns an empty sequence concept-identical to Sequence.

+
+
+

Header

+
+#include <boost/mpl/clear.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceExtensible Sequence or +Extensible Associative SequenceA sequence to get an empty "copy" of.
+
+
+

Expression semantics

+

For any Extensible Sequence or Extensible Associative Sequence s:

+
+typedef clear<s>::type t; 
+
+ +++ + + + + + + + +
Return type:Extensible Sequence or Extensible Associative Sequence.
Semantics:

Equivalent to

+
+typedef erase< s, begin<s>::type, end<s>::type >::type t;
+
+
Postcondition:empty<s>::value == true.
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef vector_c<int,1,3,5,7,9,11> odds;
+typedef clear<odds>::type nothing;
+
+BOOST_MPL_ASSERT(( empty<nothing> ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/comparisons.html b/doc/refmanual/comparisons.html new file mode 100644 index 0000000..6d7bee8 --- /dev/null +++ b/doc/refmanual/comparisons.html @@ -0,0 +1,31 @@ + + + + + + +The MPL Reference Manual: Comparisons + + + + + +
Front Page / Metafunctions / Comparisons
+ + + + + + diff --git a/doc/refmanual/components.html b/doc/refmanual/components.html new file mode 100644 index 0000000..13cb4e4 --- /dev/null +++ b/doc/refmanual/components.html @@ -0,0 +1,173 @@ + + + + + + +The MPL Reference Manual: Components + + + + + +
Front Page / Categorized Index / Components
+
+

Components

+ + +
+ + + + + diff --git a/doc/refmanual/composition-and-argument.html b/doc/refmanual/composition-and-argument.html new file mode 100644 index 0000000..62fdcd8 --- /dev/null +++ b/doc/refmanual/composition-and-argument.html @@ -0,0 +1,31 @@ + + + + + + +The MPL Reference Manual: Composition and Argument Binding + + + + + +
Front Page / Metafunctions / Composition and Argument Binding
+ + + + + + diff --git a/doc/refmanual/concepts.html b/doc/refmanual/concepts.html new file mode 100644 index 0000000..3d3086c --- /dev/null +++ b/doc/refmanual/concepts.html @@ -0,0 +1,57 @@ + + + + + + +The MPL Reference Manual: Concepts + + + + + +
Front Page / Sequences / Concepts
+
+

Concepts

+

The taxonomy of sequence concepts in MPL parallels the taxonomy of the MPL +Iterators, with two additional classification dimensions: +extensibility and associativeness.

+ + + + +
+ + + + + diff --git a/doc/refmanual/configuration.html b/doc/refmanual/configuration.html new file mode 100644 index 0000000..b06733e --- /dev/null +++ b/doc/refmanual/configuration.html @@ -0,0 +1,33 @@ + + + + + + +The MPL Reference Manual: Configuration + + + + + +
Front Page / Macros / Configuration
+ + + + + + diff --git a/doc/refmanual/contains.html b/doc/refmanual/contains.html new file mode 100644 index 0000000..f28a524 --- /dev/null +++ b/doc/refmanual/contains.html @@ -0,0 +1,112 @@ + + + + + + +The MPL Reference Manual: contains + + + + + +
Front Page / Algorithms / Querying Algorithms / contains
+
+

contains

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename T
+    >
+struct contains
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a true-valued Integral Constant if one or more elements in Sequence +are identical to T.

+
+
+

Header

+
+#include <boost/mpl/contains.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceA sequence to be examined.
TAny typeA type to search for.
+
+
+

Expression semantics

+

For any Forward Sequence s and arbitrary type t:

+
+typedef contains<s,t>::type r;
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+typedef not_< is_same< 
+      find<s,t>::type
+    , end<s>::type
+    > >::type r;
+
+
+
+
+

Complexity

+

Linear. At most size<s>::value comparisons for identity.

+
+
+

Example

+
+typedef vector<char,int,unsigned,long,unsigned long> types;
+BOOST_MPL_ASSERT_NOT(( contains<types,bool> ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/copy-if.html b/doc/refmanual/copy-if.html new file mode 100644 index 0000000..f9e8e3c --- /dev/null +++ b/doc/refmanual/copy-if.html @@ -0,0 +1,142 @@ + + + + + + +The MPL Reference Manual: copy_if + + + + + +
Front Page / Algorithms / Transformation Algorithms / copy_if
+
+

copy_if

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename Pred
+    , typename In = unspecified
+    >
+struct copy_if
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a filtered copy of the original sequence containing the elements that satisfy +the predicate Pred.

+

[Note: This wording applies to a no-inserter version(s) of the algorithm. See the +Expression semantics subsection for a precise specification of the algorithm's +details in all cases — end note]

+
+
+

Header

+
+#include <boost/mpl/copy_if.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceA sequence to copy.
PredUnary Lambda ExpressionA copying condition.
InInserterAn inserter.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Reversible Algorithm.

+

For any Forward Sequence s, an unary Lambda Expression pred, and +an Inserter in:

+
+typedef copy_if<s,pred,in>::type r; 
+
+ +++ + + + + + +
Return type:A type.
Semantics:

Equivalent to

+
+typedef lambda<pred>::type p;
+typedef lambda<in::operation>::type op;
+
+typedef fold<
+      s
+    , in::state
+    , eval_if<
+          apply_wrap1<p,_2>
+        , apply_wrap2<op,_1,_2>
+        , identity<_1>
+        >
+    >::type r;
+
+
+
+
+

Complexity

+

Linear. Exactly size<s>::value applications of pred, and at +most size<s>::value applications of in::operation.

+
+
+

Example

+
+typedef copy_if<
+      range_c<int,0,10>
+    , less< _1, int_<5> >
+    , back_inserter< vector<> >
+    >::type result;
+
+BOOST_MPL_ASSERT_RELATION( size<result>::value, ==, 5 );
+BOOST_MPL_ASSERT(( equal<result,range_c<int,0,5> > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/copy.html b/doc/refmanual/copy.html new file mode 100644 index 0000000..eb8d4a9 --- /dev/null +++ b/doc/refmanual/copy.html @@ -0,0 +1,123 @@ + + + + + + +The MPL Reference Manual: copy + + + + + +
Front Page / Algorithms / Transformation Algorithms / copy
+
+

copy

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename In = unspecified
+    >
+struct copy
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a copy of the original sequence.

+

[Note: This wording applies to a no-inserter version(s) of the algorithm. See the +Expression semantics subsection for a precise specification of the algorithm's +details in all cases — end note]

+
+
+

Header

+
+#include <boost/mpl/copy.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceA sequence to copy.
InInserterAn inserter.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Reversible Algorithm.

+

For any Forward Sequence s, and an Inserter in:

+
+typedef copy<s,in>::type r; 
+
+ +++ + + + + + +
Return type:A type.
Semantics:

Equivalent to

+
+typedef fold< s,in::state,in::operation >::type r;
+
+
+
+
+

Complexity

+

Linear. Exactly size<s>::value applications of in::operation.

+
+
+

Example

+
+typedef vector_c<int,0,1,2,3,4,5,6,7,8,9> numbers;
+typedef copy<
+      range_c<int,10,20>
+    , back_inserter< numbers >
+    >::type result;
+
+BOOST_MPL_ASSERT_RELATION( size<result>::value, ==, 20 );
+BOOST_MPL_ASSERT(( equal< result,range_c<int,0,20> > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/count-if.html b/doc/refmanual/count-if.html new file mode 100644 index 0000000..4f0cac5 --- /dev/null +++ b/doc/refmanual/count-if.html @@ -0,0 +1,116 @@ + + + + + + +The MPL Reference Manual: count_if + + + + + +
Front Page / Algorithms / Querying Algorithms / count_if
+
+

count_if

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename Pred
+    >
+struct count_if
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the number of elements in Sequence that satisfy the predicate Pred.

+
+
+

Header

+
+#include <boost/mpl/count_if.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceA sequence to be examined.
PredUnary Lambda ExpressionA count condition.
+
+
+

Expression semantics

+

For any Forward Sequence s and unary Lambda Expression pred:

+
+typedef count_if<s,pred>::type n; 
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+typedef lambda<pred>::type p;
+typedef fold< 
+      s
+    , long_<0>
+    , if_< apply_wrap1<p,_2>, next<_1>, _1 >
+    >::type n;
+
+
+
+
+

Complexity

+

Linear. Exactly size<s>::value applications of pred.

+
+
+

Example

+
+typedef vector<int,char,long,short,char,long,double,long> types;
+    
+BOOST_MPL_ASSERT_RELATION( (count_if< types, is_float<_> >::value), ==, 1 );
+BOOST_MPL_ASSERT_RELATION( (count_if< types, is_same<_,char> >::value), ==, 2 );
+BOOST_MPL_ASSERT_RELATION( (count_if< types, is_same<_,void> >::value), ==, 0 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/count.html b/doc/refmanual/count.html new file mode 100644 index 0000000..7506704 --- /dev/null +++ b/doc/refmanual/count.html @@ -0,0 +1,110 @@ + + + + + + +The MPL Reference Manual: count + + + + + +
Front Page / Algorithms / Querying Algorithms / count
+
+

count

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename T
+    >
+struct count
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the number of elements in a Sequence that are identical to T.

+
+
+

Header

+
+#include <boost/mpl/count.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceA sequence to be examined.
TAny typeA type to search for.
+
+
+

Expression semantics

+

For any Forward Sequence s and arbitrary type t:

+
+typedef count<s,t>::type n;
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+typedef count_if< s,is_same<_,T> >::type n;
+
+
+
+
+

Complexity

+

Linear. Exactly size<s>::value comparisons for identity.

+
+
+

Example

+
+typedef vector<int,char,long,short,char,short,double,long> types;
+typedef count<types, short>::type n;
+
+BOOST_MPL_ASSERT_RELATION( n::value, ==, 2 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/data-concepts.html b/doc/refmanual/data-concepts.html new file mode 100644 index 0000000..e37a500 --- /dev/null +++ b/doc/refmanual/data-concepts.html @@ -0,0 +1,25 @@ + + + + + + +The MPL Reference Manual: Concepts + + + + + +
Front Page / Data Types / Concepts
+ + + + + + diff --git a/doc/refmanual/data-miscellaneous.html b/doc/refmanual/data-miscellaneous.html new file mode 100644 index 0000000..d530f72 --- /dev/null +++ b/doc/refmanual/data-miscellaneous.html @@ -0,0 +1,27 @@ + + + + + + +The MPL Reference Manual: Miscellaneous + + + + + +
Front Page / Data Types / Miscellaneous
+ + + + + + diff --git a/doc/refmanual/data-types.html b/doc/refmanual/data-types.html new file mode 100644 index 0000000..c4c9d7a --- /dev/null +++ b/doc/refmanual/data-types.html @@ -0,0 +1,27 @@ + + + + + + +The MPL Reference Manual: Data Types + + + + + +
Front Page / Data Types
+ + + + + + diff --git a/doc/refmanual/deque.html b/doc/refmanual/deque.html new file mode 100644 index 0000000..c92c40b --- /dev/null +++ b/doc/refmanual/deque.html @@ -0,0 +1,63 @@ + + + + + + +The MPL Reference Manual: deque + + + + + +
Front Page / Sequences / Classes / deque
+
+

deque

+
+

Description

+

deque is a variadic, random access, extensible sequence of types that +supports constant-time insertion and removal of elements at both ends, and +linear-time insertion and removal of elements in the middle. In this implementation +of the library, deque is a synonym for vector.

+
+
+

Header

+
+#include <boost/mpl/deque.hpp>
+
+
+ +
+

Expression semantics

+

See vector specification.

+
+
+

Example

+
+typedef deque<float,double,long double> floats;
+typedef push_back<floats,int>::type types;
+
+BOOST_MPL_ASSERT(( is_same< at_c<types,3>::type, int > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/deref.html b/doc/refmanual/deref.html new file mode 100644 index 0000000..e4c6efe --- /dev/null +++ b/doc/refmanual/deref.html @@ -0,0 +1,109 @@ + + + + + + +The MPL Reference Manual: deref + + + + + +
Front Page / Iterators / Iterator Metafunctions / deref
+
+

deref

+
+

Synopsis

+
+template<
+      typename Iterator
+    >
+struct deref
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Dereferences an iterator.

+
+
+

Header

+
+#include <boost/mpl/deref.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
IteratorForward IteratorThe iterator to dereference.
+
+
+

Expression semantics

+

For any Forward Iterators iter:

+
+typedef deref<iter>::type t; 
+
+ +++ + + + + + + + +
Return type:A type.
Precondition:iter is dereferenceable.
Semantics:

t is identical to the element referenced by iter. If iter is +a user-defined iterator, the library-provided default implementation is +equivalent to

+
+typedef iter::type t;
+
+
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef vector<char,short,int,long> types;
+typedef begin<types>::type iter;
+
+BOOST_MPL_ASSERT(( is_same< deref<iter>::type, char > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/distance.html b/doc/refmanual/distance.html new file mode 100644 index 0000000..f7c2f06 --- /dev/null +++ b/doc/refmanual/distance.html @@ -0,0 +1,124 @@ + + + + + + +The MPL Reference Manual: distance + + + + + +
Front Page / Iterators / Iterator Metafunctions / distance
+
+

distance

+
+

Synopsis

+
+template<
+      typename First
+    , typename Last
+    >
+struct distance
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the distance between First and Last iterators, that is, an +Integral Constant n such that advance<First,n>::type is +identical to Last.

+
+
+

Header

+
+#include <boost/mpl/distance.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
First, +LastForward IteratorIterators to compute a +distance between.
+
+ +
+

Expression semantics

+

For any Forward Iterators first and last:

+
+typedef distance<first,last>::type n; 
+
+ +++ + + + + + + + + + +
Return type:Integral Constant.
Precondition:[first, last) is a valid range.
Semantics:

Equivalent to

+
+typedef iter_fold<
+      iterator_range<first,last>
+    , long_<0>
+    , next<_1>
+    >::type n;
+
+
Postcondition:is_same< advance<first,n>::type, last >::value == true.
+
+
+

Complexity

+

Amortized constant time if first and last are Random Access Iterators, +otherwise linear time.

+
+
+

Example

+
+typedef range_c<int,0,10>::type range;
+typedef begin<range>::type first;
+typedef end<range>::type last;
+
+BOOST_MPL_ASSERT_RELATION( (distance<first,last>::value), ==, 10);
+
+
+ +
+ + + + + diff --git a/doc/refmanual/divides.html b/doc/refmanual/divides.html new file mode 100644 index 0000000..06fda85 --- /dev/null +++ b/doc/refmanual/divides.html @@ -0,0 +1,144 @@ + + + + + + +The MPL Reference Manual: divides + + + + + +
Front Page / Metafunctions / Arithmetic Operations / divides
+
+

divides

+
+

Synopsis

+
+template<
+      typename T1
+    , typename T2
+    , typename T3 = unspecified
+    ...
+    , typename Tn = unspecified
+    >
+struct divides
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the quotient of its arguments.

+
+ + +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
T1, T2,... TnIntegral ConstantOperation's arguments.
+

[Note: The requirements listed in this specification +are the ones imposed by the default implementation. See Numeric Metafunction concept +for the details on how to provide an implementation for a user-defined numeric type +that does not satisfy the Integral Constant requirements. — end note]

+
+
+

Expression semantics

+

For any Integral Constants c1,c2,... cn:

+
+typedef divides<c1,...cn>::type r; 
+
+ +++ + + + + + + + +
Return type:Integral Constant.
Precondition:c2::value != 0, ... cn::value != 0.
Semantics:

Equivalent to

+
+typedef integral_c<
+      typeof(c1::value / c2::value)
+    , ( c1::value / c2::value )
+    > c;
+    
+typedef divides<c,c3,...cn>::type r; 
+
+
+ +
+typedef divides<c1,...cn> r;
+
+ +++ + + + + + + + +
Return type:Integral Constant.
Precondition:c2::value != 0, ... cn::value != 0.
Semantics:

Equivalent to

+
+struct r : divides<c1,...cn>::type {};
+
+
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef divides< int_<-10>, int_<3>, long_<1> >::type r;
+BOOST_MPL_ASSERT_RELATION( r::value, ==, -3 );
+BOOST_MPL_ASSERT(( is_same< r::value_type, long > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/empty-base.html b/doc/refmanual/empty-base.html new file mode 100644 index 0000000..42b5b19 --- /dev/null +++ b/doc/refmanual/empty-base.html @@ -0,0 +1,44 @@ + + + + + + +The MPL Reference Manual: empty_base + + + + + +
Front Page / Data Types / Miscellaneous / empty_base
+
+

empty_base

+
+

Synopsis

+
+struct empty_base {};
+
+
+
+

Description

+

An empty base class. Inheritance from empty_base through the inherit +metafunction is a no-op.

+
+
+

Header

+
+#include <boost/mpl/empty_base.hpp>
+
+
+ +
+ + + + + diff --git a/doc/refmanual/empty-sequence.html b/doc/refmanual/empty-sequence.html new file mode 100644 index 0000000..af4892b --- /dev/null +++ b/doc/refmanual/empty-sequence.html @@ -0,0 +1,89 @@ + + + + + + +The MPL Reference Manual: empty_sequence + + + + + +
Front Page / Sequences / Views / empty_sequence
+
+

empty_sequence

+
+

Synopsis

+
+struct empty_sequence
+{
+    // unspecified
+    // ...
+};
+
+
+
+

Description

+

Represents a sequence containing no elements.

+
+ +
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Random Access Sequence.

+

In the following table, s is an instance of empty_sequence.

+ ++++ + + + + + + + + + + + + + +
ExpressionSemantics
empty_sequenceAn empty Random Access Sequence.
size<s>::typesize<s>::value == 0; see Random Access Sequence.
+
+
+

Example

+
+typedef begin<empty_sequence>::type first;
+typedef end<empty_sequence>::type last;
+
+BOOST_MPL_ASSERT(( is_same<first,last> ));
+BOOST_MPL_ASSERT_RELATION( size<empty_sequence>::value, ==, 0 );
+
+typedef transform_view<
+      empty_sequence
+    , add_pointer<_>
+    > empty_view;
+
+BOOST_MPL_ASSERT_RELATION( size<empty_sequence>::value, ==, 0 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/empty.html b/doc/refmanual/empty.html new file mode 100644 index 0000000..3be9254 --- /dev/null +++ b/doc/refmanual/empty.html @@ -0,0 +1,109 @@ + + + + + + +The MPL Reference Manual: empty + + + + + +
Front Page / Sequences / Intrinsic Metafunctions / empty
+
+

empty

+
+

Synopsis

+
+template<
+      typename Sequence
+    >
+struct empty
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns an Integral Constant c such that c::value == true if +and only if the sequence is empty.

+
+
+

Header

+
+#include <boost/mpl/empty.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceA sequence to test.
+
+
+

Expression semantics

+

For any Forward Sequence s:

+
+typedef empty<s>::type c; 
+
+ +++ + + + + + + + +
Return type:Boolean Integral Constant.
Semantics:Equivalent to typedef is_same< begin<s>::type,end<s>::type >::type c;.
Postcondition:empty<s>::value == ( size<s>::value == 0 ).
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef range_c<int,0,0> empty_range;
+typedef vector<long,float,double> types;
+
+BOOST_MPL_ASSERT( empty<empty_range> );
+BOOST_MPL_ASSERT_NOT( empty<types> );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/end.html b/doc/refmanual/end.html new file mode 100644 index 0000000..822caea --- /dev/null +++ b/doc/refmanual/end.html @@ -0,0 +1,111 @@ + + + + + + +The MPL Reference Manual: end + + + + + +
Front Page / Sequences / Intrinsic Metafunctions / end
+
+

end

+
+

Synopsis

+
+template<
+      typename X
+    >
+struct end
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the sequence's past-the-end iterator. If the argument is not a +Forward Sequence, returns void_.

+
+
+

Header

+
+#include <boost/mpl/begin_end.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
XAny typeA type whose end iterator, if any, will be +returned.
+
+
+

Expression semantics

+

For any arbitrary type x:

+
+typedef end<x>::type last; 
+
+ +++ + + + + + + + +
Return type:Forward Iterator or void_.
Semantics:If x is Forward Sequence, last is an iterator pointing one past the +last element in s; otherwise last is void_.
Postcondition:If last is an iterator, it is past-the-end.
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef vector<long> v;
+typedef begin<v>::type first;
+typedef end<v>::type last;
+
+BOOST_MPL_ASSERT(( is_same< next<first>::type, last > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/equal-to.html b/doc/refmanual/equal-to.html new file mode 100644 index 0000000..cadaac7 --- /dev/null +++ b/doc/refmanual/equal-to.html @@ -0,0 +1,132 @@ + + + + + + +The MPL Reference Manual: equal_to + + + + + +
Front Page / Metafunctions / Comparisons / equal_to
+
+

equal_to

+
+

Synopsis

+
+template<
+      typename T1
+    , typename T2
+    >
+struct equal_to
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a true-valued Integral Constant if T1 and T2 are equal.

+
+ + +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
T1, T2Integral ConstantOperation's arguments.
+

[Note: The requirements listed in this specification +are the ones imposed by the default implementation. See Numeric Metafunction concept +for the details on how to provide an implementation for a user-defined numeric type +that does not satisfy the Integral Constant requirements. — end note]

+
+
+

Expression semantics

+

For any Integral Constants c1 and c2:

+
+typedef equal_to<c1,c2>::type r; 
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+typedef bool_< (c1::value == c2::value) > r;
+
+
+ +
+typedef equal_to<c1,c2> r; 
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+struct r : equal_to<c1,c2>::type {};
+
+
+
+
+

Complexity

+

Amortized constant time.

+
+ + +
+ + + + + diff --git a/doc/refmanual/equal.html b/doc/refmanual/equal.html new file mode 100644 index 0000000..7b7f534 --- /dev/null +++ b/doc/refmanual/equal.html @@ -0,0 +1,112 @@ + + + + + + +The MPL Reference Manual: equal + + + + + +
Front Page / Algorithms / Querying Algorithms / equal
+
+

equal

+
+

Synopsis

+
+template<
+      typename Seq1
+    , typename Seq2
+    , typename Pred = is_same<_1,_2>
+    >
+struct equal
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a true-valued Integral Constant if the two sequences Seq1 +and Seq2 are identical when compared element-by-element.

+
+
+

Header

+
+#include <boost/mpl/equal.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
Seq1, Seq2Forward SequenceSequences to compare.
PredBinary Lambda ExpressionA comparison criterion.
+
+
+

Expression semantics

+

For any Forward Sequences s1 and s2 and a binary Lambda Expression pred:

+
+typedef equal<s1,s2,pred>::type c; 
+
+ +++ + + + + + +
Return type:Integral Constant
Semantics:

c::value == true is and only if size<s1>::value == size<s2>::value +and for every iterator i in [begin<s1>::type, end<s1>::type) deref<i>::type is identical to

+
+advance< begin<s2>::type, distance< begin<s1>::type,i >::type >::type
+
+
+
+
+

Complexity

+

Linear. At most size<s1>::value comparisons.

+
+
+

Example

+
+typedef vector<char,int,unsigned,long,unsigned long> s1;
+typedef list<char,int,unsigned,long,unsigned long> s2;
+
+BOOST_MPL_ASSERT(( equal<s1,s2> ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/erase-key.html b/doc/refmanual/erase-key.html new file mode 100644 index 0000000..da28fe8 --- /dev/null +++ b/doc/refmanual/erase-key.html @@ -0,0 +1,116 @@ + + + + + + +The MPL Reference Manual: erase_key + + + + + +
Front Page / Sequences / Intrinsic Metafunctions / erase_key
+
+

erase_key

+
+

Synopsis

+
+template<
+      typename AssocSeq
+    , typename Key
+    >
+struct erase_key
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Erases elements associated with the key Key in the Extensible Associative Sequence +AssocSeq .

+
+
+

Header

+
+#include <boost/mpl/erase_key.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
AssocSeqExtensible Associative SequenceA sequence to erase elements from.
KeyAny typeA key for the elements to be removed.
+
+
+

Expression semantics

+

For any Extensible Associative Sequence s, and arbitrary type key:

+
+typedef erase_key<s,key>::type r; 
+
+ +++ + + + + + + + +
Return type:Extensible Associative Sequence.
Semantics:r is concept-identical and equivalent to s except that +has_key<r,k>::value == false.
Postcondition:size<r>::value == size<s>::value - 1.
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef map< pair<int,unsigned>, pair<char,long> > m;
+typedef erase_key<m,char>::type m1;
+
+BOOST_MPL_ASSERT_RELATION( size<m1>::type::value, ==, 1 );
+BOOST_MPL_ASSERT(( is_same< at<m1,char>::type,void_ > ));
+BOOST_MPL_ASSERT(( is_same< at<m1,int>::type,unsigned > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/erase.html b/doc/refmanual/erase.html new file mode 100644 index 0000000..8ff4690 --- /dev/null +++ b/doc/refmanual/erase.html @@ -0,0 +1,193 @@ + + + + + + +The MPL Reference Manual: erase + + + + + +
Front Page / Sequences / Intrinsic Metafunctions / erase
+
+

erase

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename First
+    , typename Last = unspecified
+    >
+struct erase
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

erase performs a removal of one or more adjacent elements in the sequence +starting from an arbitrary position.

+
+
+

Header

+
+#include <boost/mpl/erase.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceExtensible Sequence or +Extensible Associative SequenceA sequence to erase from.
FirstForward IteratorAn iterator to the beginning of the range to +be erased.
LastForward IteratorAn iterator past-the-end of the range to be +erased.
+
+
+

Expression semantics

+
+

For any Extensible Sequence s, and iterators pos, first and last into s:

+
+typedef erase<s,first,last>::type r; 
+
+ +++ + + + + + + + + + +
Return type:Extensible Sequence.
Precondition:[first,last) is a valid range in s.
Semantics:r is a new sequence, concept-identical to s, of the following elements: +[begin<s>::type, pos), [last, end<s>::type).
Postcondition:

The relative order of the elements in r is the same as in s;

+
+size<r>::value == size<s>::value - distance<first,last>::value
+
+
+ +
+typedef erase<s,pos>::type r;
+
+ +++ + + + + + + + +
Return type:Extensible Sequence.
Precondition:pos is a dereferenceable iterator in s.
Semantics:

Equivalent to

+
+typedef erase< s,pos,next<pos>::type >::type r;
+
+
+
+
+

For any Extensible Associative Sequence s, and iterator pos into s:

+
+typedef erase<s,pos>::type r;
+
+ +++ + + + + + + + + + +
Return type:Extensible Sequence.
Precondition:pos is a dereferenceable iterator to s.
Semantics:Erases the element at a specific position pos; equivalent to +erase_key<s, deref<pos>::type >::type.
Postcondition:size<r>::value == size<s>::value - 1.
+
+
+
+

Complexity

+ ++++ + + + + + + + + + + + + + +
Sequence archetypeComplexity (the range form)
Extensible Associative SequenceAmortized constant time.
Extensible SequenceQuadratic in the worst case, linear at best.
+
+
+

Example

+
+typedef vector_c<int,1,0,5,1,7,5,0,5> values;
+typedef find< values, integral_c<int,7> >::type pos;
+typedef erase<values,pos>::type result;
+
+BOOST_MPL_ASSERT_RELATION( size<result>::value, ==, 7 );
+
+typedef find<result, integral_c<int,7> >::type iter;
+BOOST_MPL_ASSERT(( is_same< iter, end<result>::type > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/eval-if-c.html b/doc/refmanual/eval-if-c.html new file mode 100644 index 0000000..d116f77 --- /dev/null +++ b/doc/refmanual/eval-if-c.html @@ -0,0 +1,105 @@ + + + + + + +The MPL Reference Manual: eval_if_c + + + + + +
Front Page / Metafunctions / Type Selection / eval_if_c
+
+

eval_if_c

+
+

Synopsis

+
+template< 
+      bool c
+    , typename F1
+    , typename F2
+    >
+struct eval_if_c
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Evaluates one of its two nullary-metafunction arguments, F1 or F2, depending +on the value of integral constant c. eval_if_c<c,f1,f2>::type is a shorcut +notation for eval_if< bool_<c>,f1,f2 >::type.

+
+
+

Header

+
+#include <boost/mpl/eval_if.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
cAn integral constantAn evaluation condition.
F1, F2Nullary MetafunctionMetafunctions to select for evaluation from.
+
+
+

Expression semantics

+

For any integral constant c and nullary Metafunctions f1, f2:

+
+typedef eval_if_c<c,f1,f2>::type t;
+
+ +++ + + + + + +
Return type:Any type.
Semantics:Equivalent to typedef eval_if< bool_<c>,f1,f2 >::type t;
+
+
+

Example

+
+typedef eval_if_c< true, identity<char>, identity<long> >::type t1;
+typedef eval_if_c< false, identity<char>, identity<long> >::type t2;
+
+BOOST_MPL_ASSERT(( is_same<t1,char> ));
+BOOST_MPL_ASSERT(( is_same<t2,long> ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/eval-if.html b/doc/refmanual/eval-if.html new file mode 100644 index 0000000..7a9cb28 --- /dev/null +++ b/doc/refmanual/eval-if.html @@ -0,0 +1,106 @@ + + + + + + +The MPL Reference Manual: eval_if + + + + + +
Front Page / Metafunctions / Type Selection / eval_if
+
+

eval_if

+
+

Synopsis

+
+template< 
+      typename C
+    , typename F1
+    , typename F2
+    >
+struct eval_if
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Evaluates one of its two nullary-metafunction arguments, F1 or F2, depending +on the value C.

+
+
+

Header

+
+#include <boost/mpl/eval_if.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
CIntegral ConstantAn evaluation condition.
F1, F2Nullary MetafunctionMetafunctions to select for evaluation from.
+
+
+

Expression semantics

+

For any Integral Constant c and nullary Metafunctions f1, f2:

+
+typedef eval_if<c,f1,f2>::type t;
+
+ +++ + + + + + +
Return type:Any type.
Semantics:If c::value == true, t is identical to f1::type; otherwise t is +identical to f2::type.
+
+
+

Example

+
+typedef eval_if< true_, identity<char>, identity<long> >::type t1;
+typedef eval_if< false_, identity<char>, identity<long> >::type t2;
+
+BOOST_MPL_ASSERT(( is_same<t1,char> ));
+BOOST_MPL_ASSERT(( is_same<t2,long> ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/extensible-associative.html b/doc/refmanual/extensible-associative.html new file mode 100644 index 0000000..293afad --- /dev/null +++ b/doc/refmanual/extensible-associative.html @@ -0,0 +1,131 @@ + + + + + + +The MPL Reference Manual: Extensible Associative Sequence + + + + + +
Front Page / Sequences / Concepts / Extensible Associative Sequence
+
+

Extensible Associative Sequence

+
+

Description

+

An Extensible Associative Sequence is an Associative Sequence that supports +insertion and removal of elements. In contrast to Extensible Sequence, +Extensible Associative Sequence does not provide a mechanism for +inserting an element at a specific position.

+
+
+

Expression requirements

+

In the following table and subsequent specifications, s is an Associative Sequence, +pos is an iterator into s, and x and k are arbitrary types.

+

In addition to the Associative Sequence requirements, the following must be met:

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionTypeComplexity
insert<s,x>::typeExtensible Associative SequenceAmortized constant time
insert<s,pos,x>::typeExtensible Associative SequenceAmortized constant time
erase_key<s,k>::typeExtensible Associative SequenceAmortized constant time
erase<s,pos>::typeExtensible Associative SequenceAmortized constant time
clear<s>::typeExtensible Associative SequenceAmortized constant time
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Associative Sequence.

+ ++++ + + + + + + + + + + + + + + + + + + + + + + +
ExpressionSemantics
insert<s,x>::type

Inserts x into s; the resulting sequence r is +equivalent to s except that

+
+at< r, key_type<s,x>::type >::type
+
+

is identical to value_type<s,x>::type; see insert.

+
insert<s,pos,x>::typeEquivalent to insert<s,x>::type; pos is ignored; +see insert.
erase_key<s,k>::typeErases elements in s associated with the key k; +the resulting sequence r is equivalent to s except +that has_key<r,k>::value == false; see erase_key.
erase<s,pos>::typeErases the element at a specific position; equivalent to +erase_key<s, deref<pos>::type >::type; see erase.
clear<s>::typeAn empty sequence concept-identical to s; see +clear.
+ +
+
+

Models

+ + +
+ +
+ + + + + diff --git a/doc/refmanual/extensible-sequence.html b/doc/refmanual/extensible-sequence.html new file mode 100644 index 0000000..5cae60b --- /dev/null +++ b/doc/refmanual/extensible-sequence.html @@ -0,0 +1,125 @@ + + + + + + +The MPL Reference Manual: Extensible Sequence + + + + + +
Front Page / Sequences / Concepts / Extensible Sequence
+
+

Extensible Sequence

+
+

Description

+

An Extensible Sequence is a sequence that supports insertion and removal of +elements. Extensibility is orthogonal to sequence traversal characteristics.

+
+
+

Expression requirements

+

For any Extensible Sequence s, its iterators pos and last, +Forward Sequence r, and any type x, the following expressions must +be valid:

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionTypeComplexity
insert<s,pos,x>::typeExtensible SequenceUnspecified
insert_range<s,pos,r>::typeExtensible SequenceUnspecified
erase<s,pos>::typeExtensible SequenceUnspecified
erase<s,pos,last>::typeExtensible SequenceUnspecified
clear<s>::typeExtensible SequenceConstant time
+
+
+

Expression semantics

+ ++++ + + + + + + + + + + + + + + + + + + + + + + +
ExpressionSemantics
insert<s,pos,x>::typeA new sequence, concept-identical to s, of +the following elements: +[begin<s>::type, pos), x, +[pos, end<s>::type); see insert.
insert_range<s,pos,r>::typeA new sequence, concept-identical to s, of +the following elements: +[begin<s>::type, pos), +[begin<r>::type, end<r>::type), +[pos, end<s>::type); see insert_range.
erase<s,pos>::typeA new sequence, concept-identical to s, of +the following elements: +[begin<s>::type, pos), +[next<pos>::type, end<s>::type); see erase.
erase<s,pos,last>::typeA new sequence, concept-identical to s, of +the following elements: +[begin<s>::type, pos), +[last, end<s>::type); see erase.
clear<s>::typeAn empty sequence concept-identical to s; see +clear.
+
+
+

Models

+ +
+ +
+ + + + + diff --git a/doc/refmanual/filter-view.html b/doc/refmanual/filter-view.html new file mode 100644 index 0000000..5830995 --- /dev/null +++ b/doc/refmanual/filter-view.html @@ -0,0 +1,129 @@ + + + + + + +The MPL Reference Manual: filter_view + + + + + +
Front Page / Sequences / Views / filter_view
+
+

filter_view

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename Pred
+    >
+struct filter_view
+{
+    // unspecified
+    // ...
+};
+
+
+
+

Description

+

A view into a subset of Sequence's elements satisfying the predicate Pred.

+
+ + +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceA sequence to wrap.
PredUnary Lambda ExpressionA filtering predicate.
+
+
+

Expression semantics

+

Semantics of an expression is defined only where it differs from, or is not +defined in Forward Sequence.

+

In the following table, v is an instance of filter_view, s is an arbitrary +Forward Sequence, pred is an unary Lambda Expression.

+ ++++ + + + + + + + + + + + + + +
ExpressionSemantics
+filter_view<s,pred>
+filter_view<s,pred>::type
+
+
A lazy Forward Sequence sequence of all the elements in +the range [begin<s>::type, end<s>::type) that satisfy the predicate +pred.
size<v>::typeThe size of v; +size<v>::value == count_if<s,pred>::value; +linear complexity; see Forward Sequence.
+
+
+

Example

+

Find the largest floating type in a sequence.

+
+typedef vector<int,float,long,float,char[50],long double,char> types;
+typedef max_element<
+      transform_view< filter_view< types,boost::is_float<_> >, size_of<_> >
+    >::type iter;
+
+BOOST_MPL_ASSERT(( is_same< deref<iter::base>::type, long double > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/find-if.html b/doc/refmanual/find-if.html new file mode 100644 index 0000000..f304d93 --- /dev/null +++ b/doc/refmanual/find-if.html @@ -0,0 +1,113 @@ + + + + + + +The MPL Reference Manual: find_if + + + + + +
Front Page / Algorithms / Querying Algorithms / find_if
+
+

find_if

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename Pred
+    >
+struct find_if
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns an iterator to the first element in Sequence that satisfies +the predicate Pred.

+
+
+

Header

+
+#include <boost/mpl/find_if.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceA sequence to search in.
PredUnary Lambda ExpressionA search condition.
+
+
+

Expression semantics

+

For any Forward Sequence s and unary Lambda Expression pred:

+
+typedef find_if<s,pred>::type i; 
+
+ +++ + + + + + +
Return type:Forward Iterator.
Semantics:

i is the first iterator in the range [begin<s>::type, end<s>::type) such that

+
+apply< pred,deref<i>::type >::type::value == true
+
+

If no such iterator exists, i is identical to end<s>::type.

+
+
+
+

Complexity

+

Linear. At most size<s>::value applications of pred.

+
+
+

Example

+
+typedef vector<char,int,unsigned,long,unsigned long> types;
+typedef find_if<types, is_same<_1,unsigned> >::type iter;
+
+BOOST_MPL_ASSERT(( is_same< deref<iter>::type, unsigned > ));
+BOOST_MPL_ASSERT_RELATION( iter::pos::value, ==, 2 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/find.html b/doc/refmanual/find.html new file mode 100644 index 0000000..c6f6423 --- /dev/null +++ b/doc/refmanual/find.html @@ -0,0 +1,111 @@ + + + + + + +The MPL Reference Manual: find + + + + + +
Front Page / Algorithms / Querying Algorithms / find
+
+

find

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename T
+    >
+struct find
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns an iterator to the first occurrence of type T in a Sequence.

+
+
+

Header

+
+#include <boost/mpl/find.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceA sequence to search in.
TAny typeA type to search for.
+
+
+

Expression semantics

+

For any Forward Sequence s and arbitrary type t:

+
+typedef find<s,t>::type i;
+
+ +++ + + + + + +
Return type:Forward Iterator.
Semantics:

Equivalent to

+
+typedef find_if<s, is_same<_,t> >::type i;
+
+
+
+
+

Complexity

+

Linear. At most size<s>::value comparisons for identity.

+
+
+

Example

+
+typedef vector<char,int,unsigned,long,unsigned long> types;
+typedef find<types,unsigned>::type iter;
+
+BOOST_MPL_ASSERT(( is_same< deref<iter>::type, unsigned > ));
+BOOST_MPL_ASSERT_RELATION( iter::pos::value, ==, 2 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/fold.html b/doc/refmanual/fold.html new file mode 100644 index 0000000..aec4ab8 --- /dev/null +++ b/doc/refmanual/fold.html @@ -0,0 +1,123 @@ + + + + + + +The MPL Reference Manual: fold + + + + + +
Front Page / Algorithms / Iteration Algorithms / fold
+
+

fold

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename State
+    , typename ForwardOp
+    >
+struct fold
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the result of the successive application of binary ForwardOp to the +result of the previous ForwardOp invocation (State if it's the first call) +and every element of the sequence in the range [begin<Sequence>::type, end<Sequence>::type) in order.

+
+
+

Header

+
+#include <boost/mpl/fold.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceA sequence to iterate.
StateAny typeThe initial state for the first ForwardOp +application.
ForwardOpBinary Lambda ExpressionThe operation to be executed on forward +traversal.
+
+
+

Expression semantics

+

For any Forward Sequence s, binary Lambda Expression op, and arbitrary type state:

+
+typedef fold<s,state,op>::type t; 
+
+ +++ + + + + + +
Return type:A type.
Semantics:

Equivalent to

+
+typedef iter_fold< s,state,apply<op,_1,deref<_2> > >::type t; 
+
+
+
+
+

Complexity

+

Linear. Exactly size<s>::value applications of op.

+
+
+

Example

+
+typedef vector<long,float,short,double,float,long,long double> types;
+typedef fold<
+      types
+    , int_<0>
+    , if_< is_float<_2>,next<_1>,_1 >
+    >::type number_of_floats;
+
+BOOST_MPL_ASSERT_RELATION( number_of_floats::value, ==, 4 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/forward-iterator.html b/doc/refmanual/forward-iterator.html new file mode 100644 index 0000000..bdee558 --- /dev/null +++ b/doc/refmanual/forward-iterator.html @@ -0,0 +1,147 @@ + + + + + + +The MPL Reference Manual: Forward Iterator + + + + + +
Front Page / Iterators / Concepts / Forward Iterator
+
+

Forward Iterator

+
+

Description

+

A Forward Iterator i is a type that represents a positional reference +to an element of a Forward Sequence. It allows to access the element through +a dereference operation, and provides a way to obtain an iterator to +the next element in a sequence.

+ +
+
+

Definitions

+
    +
  • An iterator can be dereferenceable, meaning that deref<i>::type +is a well-defined expression.
  • +
  • An iterator is past-the-end if it points beyond the last element of a +sequence; past-the-end iterators are non-dereferenceable.
  • +
  • An iterator i is incrementable if there is a "next" iterator, that +is, if next<i>::type expression is well-defined; past-the-end iterators are +not incrementable.
  • +
  • Two iterators into the same sequence are equivalent if they have the same +type.
  • +
  • An iterator j is reachable from an iterator i if , after recursive +application of next metafunction to i a finite number of times, i +is equivalent to j.
  • +
  • The notation [i,j) refers to a range of iterators beginning with +i and up to but not including j.
  • +
  • The range [i,j) is a valid range if j is reachable from i.
  • +
+
+
+

Expression requirements

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ExpressionTypeComplexity
deref<i>::typeAny typeAmortized constant time
next<i>::typeForward IteratorAmortized constant time
i::categoryIntegral Constant, convertible +to forward_iterator_tagConstant time
+
+
+

Expression semantics

+
+typedef deref<i>::type j;
+
+ +++ + + + + + +
Precondition:i is dereferenceable
Semantics:j is identical to the type of the pointed element
+ +
+typedef next<i>::type j;
+
+ +++ + + + + + + + +
Precondition:i is incrementable
Semantics:j is the next iterator in a sequence
Postcondition:j is dereferenceable or past-the-end
+ +
+typedef i::category c;
+
+ +++ + + + +
Semantics:c is identical to the iterator's category tag
+
+
+

Invariants

+

For any forward iterators i and j the following invariants always hold:

+
    +
  • i and j are equivalent if and only if they are pointing to the same +element.
  • +
  • If i is dereferenceable, and j is equivalent to i, then j is +dereferenceable as well.
  • +
  • If i and j are equivalent and dereferenceable, then deref<i>::type +and deref<j>::type are identical.
  • +
  • If i is incrementable, and j is equivalent to i, then j is +incrementable as well.
  • +
  • If i and j are equivalent and incrementable, then next<i>::type +and next<j>::type are equivalent.
  • +
+
+ +
+ + + + + diff --git a/doc/refmanual/forward-sequence.html b/doc/refmanual/forward-sequence.html new file mode 100644 index 0000000..1b88668 --- /dev/null +++ b/doc/refmanual/forward-sequence.html @@ -0,0 +1,136 @@ + + + + + + +The MPL Reference Manual: Forward Sequence + + + + + +
Front Page / Sequences / Concepts / Forward Sequence
+
+

Forward Sequence

+
+

Description

+

A Forward Sequence is an MPL concept representing a compile-time sequence of +elements. Sequence elements are +types, and are accessible through Iterators. The begin and end metafunctions +provide iterators delimiting the range of the sequence +elements. A sequence guarantees that its elements are arranged in a definite, +but possibly unspecified, order. Every MPL sequence is a Forward Sequence.

+
+
+

Definitions

+
    +
  • The size of a sequence is the number of elements it contains. The size is a +nonnegative number.
  • +
  • A sequence is empty if its size is zero.
  • +
+
+
+

Expression requirements

+

For any Forward Sequence s the following expressions must be valid:

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionTypeComplexity
begin<s>::typeForward IteratorAmortized constant time
end<s>::typeForward IteratorAmortized constant time
size<s>::typeIntegral ConstantUnspecified
empty<s>::typeBoolean Integral ConstantConstant time
front<s>::typeAny typeAmortized constant time
+
+
+

Expression semantics

+ ++++ + + + + + + + + + + + + + + + + + + + + + + +
ExpressionSemantics
begin<s>::typeAn iterator to the first element of the sequence; see begin.
end<s>::typeA past-the-end iterator to the sequence; see end.
size<s>::typeThe size of the sequence; see size.
empty<s>::typeA boolean Integral Constant c such that +c::value == true if and only if the sequence is empty; see empty.
front<s>::typeThe first element in the sequence; see front.
+
+
+

Invariants

+

For any Forward Sequence s the following invariants always hold:

+
    +
  • [begin<s>::type, end<s>::type) is always a valid range.
  • +
  • An algorithm that iterates through the range [begin<s>::type, end<s>::type) +will pass through every element of s exactly once.
  • +
  • begin<s>::type is identical to end<s>::type if and only if s is empty.
  • +
  • Two different iterations through s will access its elements in the same order.
  • +
+
+ + +
+ + + + + diff --git a/doc/refmanual/front-extensible-sequence.html b/doc/refmanual/front-extensible-sequence.html new file mode 100644 index 0000000..1232049 --- /dev/null +++ b/doc/refmanual/front-extensible-sequence.html @@ -0,0 +1,104 @@ + + + + + + +The MPL Reference Manual: Front Extensible Sequence + + + + + +
Front Page / Sequences / Concepts / Front Extensible Sequence
+
+

Front Extensible Sequence

+
+

Description

+

A Front Extensible Sequence is an Extensible Sequence that supports amortized constant +time insertion and removal operations at the beginning.

+
+ +
+

Expression requirements

+

In addition to the requirements defined in Extensible Sequence, +for any Back Extensible Sequence s the following must be met:

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ExpressionTypeComplexity
push_front<s,x>::typeFront Extensible SequenceAmortized constant time
pop_front<s>::typeFront Extensible SequenceAmortized constant time
front<s>::typeAny typeAmortized constant time
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Extensible Sequence.

+ ++++ + + + + + + + + + + + + + + + + +
ExpressionSemantics
push_front<s,x>::typeEquivalent to insert<s,begin<s>::type,x>::type; +see push_front.
pop_front<v>::typeEquivalent to erase<s,begin<s>::type>::type; +see pop_front.
front<s>::typeThe first element in the sequence; see front.
+
+
+

Models

+ +
+ +
+ + + + + diff --git a/doc/refmanual/front-inserter.html b/doc/refmanual/front-inserter.html new file mode 100644 index 0000000..e57b27e --- /dev/null +++ b/doc/refmanual/front-inserter.html @@ -0,0 +1,117 @@ + + + + + + +The MPL Reference Manual: front_inserter + + + + + +
Front Page / Algorithms / Inserters / front_inserter
+
+

front_inserter

+
+

Synopsis

+
+template<
+      typename Seq
+    >
+struct front_inserter
+{
+    // unspecified
+    // ...
+};
+
+
+
+

Description

+

Inserts elements at the beginning of the sequence.

+
+ + +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
SeqFront Extensible SequenceA sequence to bind the inserter to.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Inserter.

+

For any Front Extensible Sequence s:

+ ++++ + + + + + + + + + + +
ExpressionSemantics
front_inserter<s>

An Inserter in, equivalent to

+
+struct in : inserter<s,push_front<_1,_2> > {};
+
+
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef reverse_copy<
+      range_c<int,0,5>
+    , front_inserter< vector_c<int,5,6,7,8,9> >
+    >::type range;
+   
+BOOST_MPL_ASSERT(( equal< range, range_c<int,0,10> > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/front.html b/doc/refmanual/front.html new file mode 100644 index 0000000..4b0481c --- /dev/null +++ b/doc/refmanual/front.html @@ -0,0 +1,114 @@ + + + + + + +The MPL Reference Manual: front + + + + + +
Front Page / Sequences / Intrinsic Metafunctions / front
+
+

front

+
+

Synopsis

+
+template<
+      typename Sequence
+    >
+struct front
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the first element in the sequence.

+
+
+

Header

+
+#include <boost/mpl/front.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceA sequence to be examined.
+
+
+

Expression semantics

+

For any Forward Sequence s:

+
+typedef front<s>::type t; 
+
+ +++ + + + + + + + +
Return type:A type.
Precondition:empty<s>::value == false.
Semantics:

Equivalent to

+
+typedef deref< begin<s>::type >::type t;
+
+
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef list<long>::type types1;
+typedef list<int,long>::type types2;
+typedef list<char,int,long>::type types3;
+
+BOOST_MPL_ASSERT(( is_same< front<types1>::type, long > ));
+BOOST_MPL_ASSERT(( is_same< front<types2>::type, int> ));
+BOOST_MPL_ASSERT(( is_same< front<types3>::type, char> ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/greater-equal.html b/doc/refmanual/greater-equal.html new file mode 100644 index 0000000..dc34d36 --- /dev/null +++ b/doc/refmanual/greater-equal.html @@ -0,0 +1,132 @@ + + + + + + +The MPL Reference Manual: greater_equal + + + + + +
Front Page / Metafunctions / Comparisons / greater_equal
+
+

greater_equal

+
+

Synopsis

+
+template<
+      typename T1
+    , typename T2
+    >
+struct greater_equal
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a true-valued Integral Constant if T1 is greater than or equal to T2.

+
+ + +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
T1, T2Integral ConstantOperation's arguments.
+

[Note: The requirements listed in this specification +are the ones imposed by the default implementation. See Numeric Metafunction concept +for the details on how to provide an implementation for a user-defined numeric type +that does not satisfy the Integral Constant requirements. — end note]

+
+
+

Expression semantics

+

For any Integral Constants c1 and c2:

+
+typedef greater_equal<c1,c2>::type r; 
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+typedef bool_< (c1::value < c2::value) > r;
+
+
+ +
+typedef greater_equal<c1,c2> r; 
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+struct r : greater_equal<c1,c2>::type {};
+
+
+
+
+

Complexity

+

Amortized constant time.

+
+ + +
+ + + + + diff --git a/doc/refmanual/greater.html b/doc/refmanual/greater.html new file mode 100644 index 0000000..6fd2664 --- /dev/null +++ b/doc/refmanual/greater.html @@ -0,0 +1,132 @@ + + + + + + +The MPL Reference Manual: greater + + + + + +
Front Page / Metafunctions / Comparisons / greater
+
+

greater

+
+

Synopsis

+
+template<
+      typename T1
+    , typename T2
+    >
+struct greater
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a true-valued Integral Constant if T1 is greater than T2.

+
+ + +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
T1, T2Integral ConstantOperation's arguments.
+

[Note: The requirements listed in this specification +are the ones imposed by the default implementation. See Numeric Metafunction concept +for the details on how to provide an implementation for a user-defined numeric type +that does not satisfy the Integral Constant requirements. — end note]

+
+
+

Expression semantics

+

For any Integral Constants c1 and c2:

+
+typedef greater<c1,c2>::type r; 
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+typedef bool_< (c1::value < c2::value) > r;
+
+
+ +
+typedef greater<c1,c2> r; 
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+struct r : greater<c1,c2>::type {};
+
+
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+BOOST_MPL_ASSERT(( greater< int_<10>, int_<0> > ));
+BOOST_MPL_ASSERT_NOT(( greater< long_<0>, int_<10> > ));
+BOOST_MPL_ASSERT_NOT(( greater< long_<10>, int_<10> > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/has-key.html b/doc/refmanual/has-key.html new file mode 100644 index 0000000..41b9b7c --- /dev/null +++ b/doc/refmanual/has-key.html @@ -0,0 +1,113 @@ + + + + + + +The MPL Reference Manual: has_key + + + + + +
Front Page / Sequences / Intrinsic Metafunctions / has_key
+
+

has_key

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename Key
+    >
+struct has_key
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a true-valued Integral Constant if Sequence contains an element +with key Key.

+
+
+

Header

+
+#include <boost/mpl/has_key.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceAssociative SequenceA sequence to query.
KeyAny typeThe queried key.
+
+
+

Expression semantics

+

For any Associative Sequence s, and arbitrary type key:

+
+typedef has_key<s,key>::type c; 
+
+ +++ + + + + + +
Return type:Boolean Integral Constant.
Semantics:c::value == true if key is in s's set of keys; otherwise +c::value == false.
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef map< pair<int,unsigned>, pair<char,long> > m;
+BOOST_MPL_ASSERT_NOT(( has_key<m,long> ));
+
+typedef insert< m, pair<long,unsigned long> > m1;
+BOOST_MPL_ASSERT(( has_key<m1,long> ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/has-xxx-trait-def.html b/doc/refmanual/has-xxx-trait-def.html new file mode 100644 index 0000000..7f414aa --- /dev/null +++ b/doc/refmanual/has-xxx-trait-def.html @@ -0,0 +1,134 @@ + + + + + + +The MPL Reference Manual: BOOST_MPL_HAS_XXX_TRAIT_DEF + + + + + +
Front Page / Macros / Introspection / BOOST_MPL_HAS_XXX_TRAIT_DEF
+
+

BOOST_MPL_HAS_XXX_TRAIT_DEF

+
+

Synopsis

+
+#define BOOST_MPL_HAS_XXX_TRAIT_DEF(name) \
+    unspecified token sequence \
+/**/
+
+
+
+

Description

+

Expands into a definition of a boolean unary Metafunction has_name +such that for any type x has_name<x>::value == true if and only +if x is a class type and has a nested type memeber x::name.

+

On the deficient compilers not capabale of performing the detection, +has_name<x>::value always returns false. A boolean configuraion +macro, BOOST_MPL_CFG_NO_HAS_XXX, is provided to signal or override +the "deficient" status of a particular compiler.

+

[Note: BOOST_MPL_HAS_XXX_TRAIT_DEF is a simplified front end to +the BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF introspection macro — end note]

+
+
+

Header

+
+#include <boost/mpl/has_xxx.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
nameA legal identifier tokenA name of the member being detected.
+
+
+

Expression semantics

+

For any legal C++ identifier name:

+
+BOOST_MPL_HAS_XXX_TRAIT_DEF(name)
+
+ +++ + + + + + + + +
Precondition:Appears at namespace scope.
Return type:None.
Semantics:

Equivalent to

+
+BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(
+      BOOST_PP_CAT(has_,name), name, false
+    )
+
+
+
+
+

Example

+
+BOOST_MPL_HAS_XXX_TRAIT_DEF(has_xxx)
+
+struct test1 {};
+struct test2 { void xxx(); };
+struct test3 { int xxx; };
+struct test4 { static int xxx(); };
+struct test5 { template< typename T > struct xxx {}; };
+struct test6 { typedef int xxx; };
+struct test7 { struct xxx; };
+struct test8 { typedef void (*xxx)(); };
+struct test9 { typedef void (xxx)(); };
+
+BOOST_MPL_ASSERT_NOT(( has_xxx<test1> ));
+BOOST_MPL_ASSERT_NOT(( has_xxx<test2> ));
+BOOST_MPL_ASSERT_NOT(( has_xxx<test3> ));
+BOOST_MPL_ASSERT_NOT(( has_xxx<test4> ));
+BOOST_MPL_ASSERT_NOT(( has_xxx<test5> ));
+
+#if !defined(BOOST_MPL_CFG_NO_HAS_XXX)
+BOOST_MPL_ASSERT(( has_xxx<test6> ));
+BOOST_MPL_ASSERT(( has_xxx<test7> ));
+BOOST_MPL_ASSERT(( has_xxx<test8> ));
+BOOST_MPL_ASSERT(( has_xxx<test9> ));
+#endif
+
+BOOST_MPL_ASSERT(( has_xxx<test6,true_> ));
+BOOST_MPL_ASSERT(( has_xxx<test7,true_> ));
+BOOST_MPL_ASSERT(( has_xxx<test8,true_> ));
+BOOST_MPL_ASSERT(( has_xxx<test9,true_> ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/has-xxx-trait-named-def.html b/doc/refmanual/has-xxx-trait-named-def.html new file mode 100644 index 0000000..a0edcec --- /dev/null +++ b/doc/refmanual/has-xxx-trait-named-def.html @@ -0,0 +1,180 @@ + + + + + + +The MPL Reference Manual: BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF + + + + + +
Front Page / Macros / Introspection / BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF
+
+

BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF

+
+

Synopsis

+
+#define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, default_) \
+    unspecified token sequence \
+/**/
+
+
+
+

Description

+

Expands into a definition of a boolean unary Metafunction trait +such that for any type x trait<x>::value == true if and only +if x is a class type and has a nested type memeber x::name.

+

On the deficient compilers not capabale of performing the detection, +trait<x>::value always returns a fallback value default_. +A boolean configuraion macro, BOOST_MPL_CFG_NO_HAS_XXX, is provided +to signal or override the "deficient" status of a particular compiler. +[Note: The fallback value call also be provided at the point of the +metafunction invocation; see the Expression semantics section for +details — end note]

+
+
+

Header

+
+#include <boost/mpl/has_xxx.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
traitA legal identifier tokenA name of the metafunction to be generated.
nameA legal identifier tokenA name of the member being detected.
default_An boolean constantA fallback value for the deficient compilers.
+
+
+

Expression semantics

+

For any legal C++ identifiers trait and name, boolean constant expression c1, +boolean Integral Constant c2, and arbitrary type x:

+
+BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, c1)
+
+ +++ + + + + + + + +
Precondition:Appears at namespace scope.
Return type:None.
Semantics:

Expands into an equivalent of the following class template definition

+
+template< typename X, typename fallback = boost::mpl::bool_<c1> >
+struct trait
+{
+    // unspecified
+    // ...
+};
+
+

where trait is a boolean Metafunction with the following semantics:

+
+typedef trait<x>::type r;
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:If BOOST_MPL_CFG_NO_HAS_XXX is defined, r::value == c1; +otherwise, r::value == true if and only if x is a class type +that has a nested type memeber x::name.
+
+typedef trait< x,c2 >::type r;
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

If BOOST_MPL_CFG_NO_HAS_XXX is defined, r::value == c2::value; +otherwise, equivalent to

+
+typedef trait<x>::type r;
+
+
+
+
+
+

Example

+
+BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_xxx, xxx, false)
+
+struct test1 {};
+struct test2 { void xxx(); };
+struct test3 { int xxx; };
+struct test4 { static int xxx(); };
+struct test5 { template< typename T > struct xxx {}; };
+struct test6 { typedef int xxx; };
+struct test7 { struct xxx; };
+struct test8 { typedef void (*xxx)(); };
+struct test9 { typedef void (xxx)(); };
+
+BOOST_MPL_ASSERT_NOT(( has_xxx<test1> ));
+BOOST_MPL_ASSERT_NOT(( has_xxx<test2> ));
+BOOST_MPL_ASSERT_NOT(( has_xxx<test3> ));
+BOOST_MPL_ASSERT_NOT(( has_xxx<test4> ));
+BOOST_MPL_ASSERT_NOT(( has_xxx<test5> ));
+
+#if !defined(BOOST_MPL_CFG_NO_HAS_XXX)
+BOOST_MPL_ASSERT(( has_xxx<test6> ));
+BOOST_MPL_ASSERT(( has_xxx<test7> ));
+BOOST_MPL_ASSERT(( has_xxx<test8> ));
+BOOST_MPL_ASSERT(( has_xxx<test9> ));
+#endif
+
+BOOST_MPL_ASSERT(( has_xxx<test6,true_> ));
+BOOST_MPL_ASSERT(( has_xxx<test7,true_> ));
+BOOST_MPL_ASSERT(( has_xxx<test8,true_> ));
+BOOST_MPL_ASSERT(( has_xxx<test9,true_> ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/identity.html b/doc/refmanual/identity.html new file mode 100644 index 0000000..916f66e --- /dev/null +++ b/doc/refmanual/identity.html @@ -0,0 +1,108 @@ + + + + + + +The MPL Reference Manual: identity + + + + + +
Front Page / Metafunctions / Miscellaneous / identity
+
+

identity

+
+

Synopsis

+
+template< 
+      typename X
+    >
+struct identity
+{
+    typedef X type;
+};
+
+
+
+

Description

+

The identity metafunction. Returns X unchanged.

+
+
+

Header

+
+#include <boost/mpl/identity.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
XAny typeAn argument to be returned.
+
+
+

Expression semantics

+

For an arbitrary type x:

+
+typedef identity<x>::type r;
+
+ +++ + + + + + + + +
Return type:A type.
Semantics:

Equivalent to

+
+typedef x r;
+
+
Postcondition:is_same<r,x>::value == true.
+
+
+

Example

+
+typedef apply< identity<_1>, char >::type t1;
+typedef apply< identity<_2>, char,int >::type t2;
+
+BOOST_MPL_ASSERT(( is_same< t1, char > ));
+BOOST_MPL_ASSERT(( is_same< t2, int > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/if-c.html b/doc/refmanual/if-c.html new file mode 100644 index 0000000..c99dedd --- /dev/null +++ b/doc/refmanual/if-c.html @@ -0,0 +1,106 @@ + + + + + + +The MPL Reference Manual: if_c + + + + + +
Front Page / Metafunctions / Type Selection / if_c
+
+

if_c

+
+

Synopsis

+
+template< 
+      bool c
+    , typename T1
+    , typename T2
+    >
+struct if_c
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns one of its two arguments, T1 or T2, depending on the value of +integral constant c. if_c<c,t1,t2>::type is a shorcut notation for +if_< bool_<c>,t1,t2 >::type.

+
+
+

Header

+
+#include <boost/mpl/if.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
cAn integral constantA selection condition.
T1, T2Any typeTypes to select from.
+
+
+

Expression semantics

+

For any integral constant c and arbitrary types t1, t2:

+
+typedef if_c<c,t1,t2>::type t;
+
+ +++ + + + + + +
Return type:Any type.
Semantics:Equivalent to typedef if_< bool_<c>,t1,t2 >::type t;
+
+
+

Example

+
+typedef if_c<true,char,long>::type t1;
+typedef if_c<false,char,long>::type t2;
+
+BOOST_MPL_ASSERT(( is_same<t1, char> ));
+BOOST_MPL_ASSERT(( is_same<t2, long> ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/if.html b/doc/refmanual/if.html new file mode 100644 index 0000000..4bbab46 --- /dev/null +++ b/doc/refmanual/if.html @@ -0,0 +1,105 @@ + + + + + + +The MPL Reference Manual: if_ + + + + + +
Front Page / Metafunctions / Type Selection / if_
+
+

if_

+
+

Synopsis

+
+template< 
+      typename C
+    , typename T1
+    , typename T2
+    >
+struct if_
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns one of its two arguments, T1 or T2, depending on the value C.

+
+
+

Header

+
+#include <boost/mpl/if.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
CIntegral ConstantA selection condition.
T1, T2Any typeTypes to select from.
+
+
+

Expression semantics

+

For any Integral Constant c and arbitrary types t1, t2:

+
+typedef if_<c,t1,t2>::type t;
+
+ +++ + + + + + +
Return type:Any type.
Semantics:If c::value == true, t is identical to t1; otherwise t is +identical to t2.
+
+
+

Example

+
+typedef if_<true_,char,long>::type t1;
+typedef if_<false_,char,long>::type t2;
+
+BOOST_MPL_ASSERT(( is_same<t1, char> ));
+BOOST_MPL_ASSERT(( is_same<t2, long> ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/inherit-linearly.html b/doc/refmanual/inherit-linearly.html new file mode 100644 index 0000000..a962d32 --- /dev/null +++ b/doc/refmanual/inherit-linearly.html @@ -0,0 +1,152 @@ + + + + + + +The MPL Reference Manual: inherit_linearly + + + + + +
Front Page / Metafunctions / Miscellaneous / inherit_linearly
+
+

inherit_linearly

+
+

Synopsis

+
+template<
+      typename Types
+    , typename Node
+    , typename Root = empty_base
+    >
+struct inherit_linearly
+    : fold<Types,Root,Node>
+{
+};
+
+
+
+

Description

+

A convenience wrapper for fold to use in the context of sequence-driven +class composition. Returns the result the successive application of binary +Node to the result of the previous Node invocation (Root if it's +the first call) and every type in the Forward Sequence Types in order.

+
+ + +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
TypesForward SequenceTypes to inherit from.
NodeBinary Lambda ExpressionA derivation metafunction.
RootA class typeA type to be placed at the root of the class +hierarchy.
+
+
+

Expression semantics

+

For any Forward Sequence types, binary Lambda Expression node, and arbitrary +class type root:

+
+typedef inherit_linearly<types,node,root>::type r; 
+
+ +++ + + + + + +
Return type:A class type.
Semantics:

Equivalent to

+
+typedef fold<types,root,node>::type r; 
+
+
+
+
+

Complexity

+

Linear. Exactly size<types>::value applications of node.

+
+
+

Example

+
+template< typename T > struct tuple_field
+{
+    T field;
+};
+
+template< typename T >
+inline
+T& field(tuple_field<T>& t)
+{
+    return t.field;
+}
+
+typedef inherit_linearly<
+      vector<int,char const*,bool>
+    , inherit< _1, tuple_field<_2> >
+    >::type tuple;
+
+
+int main()
+{
+    tuple t;
+    
+    field<int>(t) = -1;
+    field<char const*>(t) = "text";
+    field<bool>(t) = false;
+
+    std::cout
+        << field<int>(t) << 'n'
+        << field<char const*>(t) << 'n'
+        << field<bool>(t) << 'n'
+        ;
+}
+
+
+ +
+ + + + + diff --git a/doc/refmanual/inherit.html b/doc/refmanual/inherit.html new file mode 100644 index 0000000..cdaa1df --- /dev/null +++ b/doc/refmanual/inherit.html @@ -0,0 +1,205 @@ + + + + + + +The MPL Reference Manual: inherit + + + + + +
Front Page / Metafunctions / Miscellaneous / inherit
+
+

inherit

+
+

Synopsis

+
+template<
+      typename T1, typename T2
+    >
+struct inherit2
+{
+    typedef unspecified type;
+};
+
+...
+
+template<
+      typename T1, typename T2,... typename Tn
+    >
+struct inheritn
+{
+    typedef unspecified type;
+};
+
+template<
+      typename T1
+    , typename T2
+    ...
+    , typename Tn = unspecified
+    >
+struct inherit
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns an unspecified class type publically derived from T1, T2,... Tn. +Guarantees that derivation from empty_base is always a no-op, +regardless of the position and number of empty_base classes in +T1, T2,... Tn.

+
+
+

Header

+
+#include <boost/mpl/inherit.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
T1, T2,... TnA class typeClasses to derived from.
+
+
+

Expression semantics

+

For artibrary class types t1,t2,... tn:

+
+typedef inherit2<t1,t2>::type r; 
+
+ +++ + + + + + + + +
Return type:A class type.
Precondition:t1 and t2 are complete types.
Semantics:

If both t1 and t2 are identical to empty_base, equivalent to

+
+typedef empty_base r;
+
+

otherwise, if t1 is identical to empty_base, equivalent to

+
+typedef t2 r;
+
+

otherwise, if t2 is identical to empty_base, equivalent to

+
+typedef t1 r;
+
+

otherwise equivalent to

+
+struct r : t1, t2 {};
+
+
+ +
+typedef inheritn<t1,t2,...tn>::type r; 
+
+ +++ + + + + + + + +
Return type:A class type.
Precondition:t1,t2,... tn are complete types.
Semantics:

Equivalent to

+
+struct r
+    : inherit2<
+          inheritn-1<t1,t2,...tn-1>::type
+        , tn
+        >
+{
+};
+
+
+ +
+typedef inherit<t1,t2,...tn>::type r; 
+
+ +++ + + + + + + + +
Precondition:t1,t2,... tn are complete types.
Return type:A class type.
Semantics:

Equivalent to

+
+typedef inheritn<t1,t2,...tn>::type r; 
+
+
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+struct udt1 { int n; };
+struct udt2 {};
+
+typedef inherit<udt1,udt2>::type r1;
+typedef inherit<empty_base,udt1>::type r2;
+typedef inherit<empty_base,udt1,empty_base,empty_base>::type r3;
+typedef inherit<udt1,empty_base,udt2>::type r4;
+typedef inherit<empty_base,empty_base>::type r5;
+
+BOOST_MPL_ASSERT(( is_base_and_derived< udt1, r1> ));
+BOOST_MPL_ASSERT(( is_base_and_derived< udt2, r1> ));
+BOOST_MPL_ASSERT(( is_same< r2, udt1> ));    
+BOOST_MPL_ASSERT(( is_same< r3, udt1 > ));
+BOOST_MPL_ASSERT(( is_base_and_derived< udt1, r4 > ));
+BOOST_MPL_ASSERT(( is_base_and_derived< udt2, r4 > ));
+BOOST_MPL_ASSERT(( is_same< r5, empty_base > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/insert-range.html b/doc/refmanual/insert-range.html new file mode 100644 index 0000000..c4f9d47 --- /dev/null +++ b/doc/refmanual/insert-range.html @@ -0,0 +1,139 @@ + + + + + + +The MPL Reference Manual: insert_range + + + + + +
Front Page / Sequences / Intrinsic Metafunctions / insert_range
+
+

insert_range

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename Pos
+    , typename Range
+    >
+struct insert_range
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

insert_range performs an insertion of a range of elements at an arbitrary position in +the sequence.

+
+ + +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceExtensible Sequence or +Extensible Associative SequenceA sequence to insert into.
PosForward IteratorAn iterator in Sequence specifying the +insertion position.
RangeForward SequenceThe range of elements to be inserted.
+
+
+

Expression semantics

+

For any Extensible Sequence s, iterator pos in s, and Forward Sequence range:

+
+typedef insert<s,pos,range>::type r; 
+
+ +++ + + + + + + + + + +
Return type:Extensible Sequence.
Precondition:pos is an iterator into s.
Semantics:r is a sequence, concept-identical to s, of the following elements: +[begin<s>::type, pos), [begin<r>::type, end<r>::type), +[pos, end<s>::type).
Postcondition:

The relative order of the elements in r is the same as in s;

+
+size<r>::value == size<s>::value + size<range>::value 
+
+
+
+
+

Complexity

+

Sequence dependent. Quadratic in the worst case, linear at best; see the particular +sequence class' specification for details.

+
+
+

Example

+
+typedef vector_c<int,0,1,7,8,9> numbers;
+typedef find< numbers,integral_c<int,7> >::type pos;
+typedef insert_range< numbers,pos,range_c<int,2,7> >::type range;
+
+BOOST_MPL_ASSERT_RELATION( size<range>::value, ==, 10 );
+BOOST_MPL_ASSERT(( equal< range,range_c<int,0,10> > ));
+
+typedef insert_range< 
+      list0<>
+    , end< list0<> >::type
+    , list<int>
+    >::type result2;
+
+BOOST_MPL_ASSERT_RELATION( size<result2>::value, ==, 1 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/insert.html b/doc/refmanual/insert.html new file mode 100644 index 0000000..d337e42 --- /dev/null +++ b/doc/refmanual/insert.html @@ -0,0 +1,214 @@ + + + + + + +The MPL Reference Manual: insert + + + + + +
Front Page / Sequences / Intrinsic Metafunctions / insert
+
+

insert

+
+

Synopsis

+
+template< 
+      typename Sequence
+    , typename Pos
+    , typename T 
+    >
+struct insert
+{
+    typedef unspecified type;
+};
+
+
+template< 
+      typename Sequence
+    , typename T 
+    >
+struct insert
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

insert is an overloaded name:

+ +
+
+

Header

+
+#include <boost/mpl/insert.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceExtensible Sequence or +Extensible Associative SequenceA sequence to insert into.
PosForward IteratorAn iterator in Sequence specifying the +insertion position.
TAny typeThe element to be inserted.
+
+
+

Expression semantics

+
+

For any Extensible Sequence s, iterator pos in s, and arbitrary type x:

+
+typedef insert<s,pos,x>::type r; 
+
+ +++ + + + + + + + + + +
Return type:Extensible Sequence
Precondition:pos is an iterator in s.
Semantics:r is a sequence, concept-identical to s, of the following elements: +[begin<s>::type, pos), x, [pos, end<s>::type).
Postcondition:

The relative order of the elements in r is the same as in s.

+
+at< r, distance< begin<s>::type,pos >::type >::type
+
+

is identical to x;

+
+size<r>::value == size<s>::value + 1;        
+
+
+
+
+

For any Extensible Associative Sequence s, iterator pos in s, +and arbitrary type x:

+
+typedef insert<s,x>::type r; 
+
+ +++ + + + + + + + +
Return type:Extensible Associative Sequence
Semantics:r is concept-identical and equivalent to s, except that +at< r, key_type<s,x>::type >::type is identical to value_type<s,x>::type.
Postcondition:size<r>::value == size<s>::value + 1.
+ +
+typedef insert<s,pos,x>::type r; 
+
+ +++ + + + + + + + +
Return type:Extensible Associative Sequence
Precondition:pos is an iterator in s.
Semantics:Equivalent to typedef insert<s,x>::type r; pos is ignored.
+
+
+
+

Complexity

+ ++++ + + + + + + + + + + + + + +
Sequence archetypeComplexity
Extensible Associative SequenceAmortized constant time.
Extensible SequenceLinear in the worst case, or amortized +constant time.
+
+
+

Example

+
+typedef vector_c<int,0,1,3,4,5,6,7,8,9> numbers;
+typedef find< numbers,integral_c<int,3> >::type pos;
+typedef insert< numbers,pos,integral_c<int,2> >::type range;
+
+BOOST_MPL_ASSERT_RELATION( size<range>::value, ==, 10 );
+BOOST_MPL_ASSERT(( equal< range,range_c<int,0,10> > ));
+
+
+typedef map< mpl::pair<int,unsigned> > m;
+typedef insert<m,mpl::pair<char,long> >::type m1;
+
+BOOST_MPL_ASSERT_RELATION( size<m1>::value, ==, 2 );
+BOOST_MPL_ASSERT(( is_same< at<m1,int>::type,unsigned > ));
+BOOST_MPL_ASSERT(( is_same< at<m1,char>::type,long > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/inserter.html b/doc/refmanual/inserter.html new file mode 100644 index 0000000..94bc653 --- /dev/null +++ b/doc/refmanual/inserter.html @@ -0,0 +1,107 @@ + + + + + + +The MPL Reference Manual: Inserter + + + + + +
Front Page / Algorithms / Concepts / Inserter
+
+

Inserter

+
+

Description

+

An Inserter is a compile-time substitute for STL Output Iterator. +Under the hood, it's simply a type holding +two entities: a state and an operation. When passed to a +transformation algorithm, the inserter's binary operation is +invoked for every element that would normally be written into the +output iterator, with the element itself (as the second +argument) and the result of the previous operation's invocation — or, +for the very first element, the inserter's initial state.

+

Technically, instead of taking a single inserter parameter, +transformation algorithms could accept the state and the "output" +operation separately. Grouping these in a single parameter entity, +however, brings the algorithms semantically and syntactically closer to +their STL counterparts, significantly simplifying many of the common +use cases.

+
+
+

Valid expressions

+

In the following table and subsequent specifications, in is a model of Inserter.

+ ++++ + + + + + + + + + + + + + +
ExpressionType
in::stateAny type
in::operationBinary Lambda Expression
+
+
+

Expression semantics

+ ++++ + + + + + + + + + + + + + +
ExpressionSemantics
in::stateThe inserter's initial state.
in::operationThe inserter's "output" operation.
+
+
+

Example

+
+typedef transform<
+      range_c<int,0,10>
+    , plus<_1,_1>
+    , back_inserter< vector0<> >
+    >::type result;
+
+
+ + +
+ + + + + diff --git a/doc/refmanual/inserters-inserter.html b/doc/refmanual/inserters-inserter.html new file mode 100644 index 0000000..f2c2ef6 --- /dev/null +++ b/doc/refmanual/inserters-inserter.html @@ -0,0 +1,122 @@ + + + + + + +The MPL Reference Manual: inserter + + + + + +
Front Page / Algorithms / Inserters / inserter
+
+

inserter

+
+

Synopsis

+
+template<
+      typename State
+    , typename Operation
+    >
+struct inserter
+{
+    typedef State state;
+    typedef Operation operation;
+};
+
+
+
+

Description

+

A general-purpose model of the Inserter concept.

+
+
+

Header

+
+#include <boost/mpl/inserter.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
StateAny typeA initial state.
OperationBinary Lambda ExpressionAn output operation.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Inserter.

+

For any binary Lambda Expression op and arbitrary type state:

+ ++++ + + + + + + + + + + +
ExpressionSemantics
inserter<op,state>An Inserter.
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+template< typename N > struct is_odd : bool_< ( N::value % 2 ) > {};
+
+typedef copy<
+      range_c<int,0,10>
+    , inserter< // a filtering 'push_back' inserter
+          vector<>
+        , if_< is_odd<_2>, push_back<_1,_2>, _1 >
+        >
+    >::type odds;
+   
+BOOST_MPL_ASSERT(( equal< odds, vector_c<int,1,3,5,7,9>, equal_to<_,_> > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/inserters.html b/doc/refmanual/inserters.html new file mode 100644 index 0000000..492aaab --- /dev/null +++ b/doc/refmanual/inserters.html @@ -0,0 +1,27 @@ + + + + + + +The MPL Reference Manual: Inserters + + + + + +
Front Page / Algorithms / Inserters
+ + + + + + diff --git a/doc/refmanual/int.html b/doc/refmanual/int.html new file mode 100644 index 0000000..f14276a --- /dev/null +++ b/doc/refmanual/int.html @@ -0,0 +1,112 @@ + + + + + + +The MPL Reference Manual: int_ + + + + + +
Front Page / Data Types / Numeric / int_
+
+

int_

+
+

Synopsis

+
+template<
+      int N
+    >
+struct int_
+{
+    // unspecified
+    // ...
+};
+
+
+
+

Description

+

An Integral Constant wrapper for int.

+
+
+

Header

+
+#include <boost/mpl/int.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
NAn integral constantA value to wrap.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Integral Constant.

+

For arbitrary integral constant n:

+ ++++ + + + + + + + + + + +
ExpressionSemantics
int_<c>An Integral Constant x such that x::value == c +and x::value_type is identical to int.
+
+
+

Example

+
+typedef int_<8> eight;
+
+BOOST_MPL_ASSERT(( is_same< eight::value_type, int > ));
+BOOST_MPL_ASSERT(( is_same< eight::type, eight > ));
+BOOST_MPL_ASSERT(( is_same< next< eight >::type, int_<9> > ));
+BOOST_MPL_ASSERT(( is_same< prior< eight >::type, int_<7> > ));
+BOOST_MPL_ASSERT_RELATION( (eight::value), ==, 8 );
+assert( eight() == 8 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/integral-c.html b/doc/refmanual/integral-c.html new file mode 100644 index 0000000..889dd77 --- /dev/null +++ b/doc/refmanual/integral-c.html @@ -0,0 +1,115 @@ + + + + + + +The MPL Reference Manual: integral_c + + + + + +
Front Page / Data Types / Numeric / integral_c
+
+

integral_c

+
+

Synopsis

+
+template<
+      typename T, T N
+    >
+struct integral_c
+{
+    // unspecified
+    // ...
+};
+
+
+
+

Description

+

A generic Integral Constant wrapper.

+
+
+

Header

+
+#include <boost/mpl/integral_c.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
TAn integral typeWrapper's value type.
NAn integral constantA value to wrap.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Integral Constant.

+

For arbitrary integral type t and integral constant n:

+ ++++ + + + + + + + + + + +
ExpressionSemantics
integral_c<t,c>An Integral Constant x such that x::value == c +and x::value_type is identical to t.
+
+
+

Example

+
+typedef integral_c<short,8> eight;
+
+BOOST_MPL_ASSERT(( is_same< eight::value_type, short > ));
+BOOST_MPL_ASSERT(( is_same< eight::type, eight > ));
+BOOST_MPL_ASSERT(( is_same< next< eight >::type, integral_c<short,9> > ));
+BOOST_MPL_ASSERT(( is_same< prior< eight >::type, integral_c<short,7> > ));
+BOOST_MPL_ASSERT_RELATION( (eight::value), ==, 8 );
+assert( eight() == 8 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/integral-constant.html b/doc/refmanual/integral-constant.html new file mode 100644 index 0000000..c5e8d5c --- /dev/null +++ b/doc/refmanual/integral-constant.html @@ -0,0 +1,121 @@ + + + + + + +The MPL Reference Manual: Integral Constant + + + + + +
Front Page / Data Types / Concepts / Integral Constant
+
+

Integral Constant

+
+

Description

+

An Integral Constant is a holder class for a compile-time value of an +integral type. Every Integral Constant is also a nullary Metafunction, +returning itself. An integral constant object is implicitly convertible to the +corresponding run-time value of the wrapped integral type.

+
+
+

Expression requirements

+

In the following table and subsequent specifications, n is a model of Integral Constant.

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionTypeComplexity
n::value_typeAn integral typeConstant time.
n::valueAn integral constant expressionConstant time.
n::typeIntegral ConstantConstant time.
next<n>::typeIntegral ConstantConstant time.
prior<n>::typeIntegral ConstantConstant time.
n::value_type const c = n() Constant time.
+
+
+

Expression semantics

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionSemantics
n::value_typeA cv-unqualified type of n::value.
n::valueThe value of the wrapped integral constant.
n::typeis_same<n::type,n>::value == true.
next<n>::typeAn Integral Constant c of type n::value_type +such that c::value == n::value + 1.
prior<n>::typeAn Integral Constant c of type n::value_type +such that c::value == n::value - 1.
n::value_type const c = n()c == n::value.
+
+ + +
+ + + + + diff --git a/doc/refmanual/integral-sequence-wrapper.html b/doc/refmanual/integral-sequence-wrapper.html new file mode 100644 index 0000000..406a647 --- /dev/null +++ b/doc/refmanual/integral-sequence-wrapper.html @@ -0,0 +1,153 @@ + + + + + + +The MPL Reference Manual: Integral Sequence Wrapper + + + + + +
Front Page / Sequences / Concepts / Integral Sequence Wrapper
+
+

Integral Sequence Wrapper

+
+

Description

+

An Integral Sequence Wrapper is a class template that provides a concise +interface for creating a corresponding sequence of Integral Constants. In +particular, assuming that seq is a name of the wrapper's underlying +sequence and c1,c2,... cn are integral constants of an integral type T to +be stored in the sequence, the wrapper provides us with the following +notation:

+
+
+
seq_c<T,c1,c2,... cn>
+
+
+

If seq is a Variadic Sequence, numbered wrapper forms are +also avaialable:

+
+
+
seqn_c<T,c1,c2,... cn>
+
+
+
+
+

Expression requirements

+

In the following table and subsequent specifications, seq is a placeholder token for the +Integral Sequence Wrapper's underlying sequence's name.

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionTypeComplexity
seq_c<T,c1,c2,... cn>Forward SequenceAmortized constant time.
seq_c<T,c1,c2,... cn>::typeForward SequenceAmortized constant time.
seq_c<T,c1,c2,... cn>::value_typeAn integral typeAmortized constant time.
seqn_c<T,c1,c2,... cn>Forward SequenceAmortized constant time.
seqn_c<T,c1,c2,... cn>::typeForward SequenceAmortized constant time.
seqn_c<T,c1,c2,... cn>::value_typeAn integral typeAmortized constant time.
+
+
+

Expression semantics

+
+typedef seq_c<T,c1,c2,... cn> s;
+typedef seqn_c<T,c1,c2,... cn> s;
+
+ +++ + + + + + +
Semantics:s is a sequence seq of integral constant wrappers integral_c<T,c1>, +integral_c<T,c2>, ... integral_c<T,cn>.
Postcondition:

size<s>::value == n.

+ +
+ +
+typedef seq_c<T,c1,c2,... cn>::type s;
+typedef seqn_c<T,c1,c2,... cn>::type s;
+
+ +++ + + + +
Semantics:s is identical to +seqn<integral_c<T,c1>,integral_c<T,c2>, +... integral_c<T,cn> >.
+ +
+typedef seq_c<T,c1,c2,... cn>::value_type t;
+typedef seqn_c<T,c1,c2,... cn>::value_type t;
+
+ +++ + + + +
Semantics:is_same<t,T>::value == true.
+
+ + +
+ + + + + diff --git a/doc/refmanual/intrinsic-metafunctions.html b/doc/refmanual/intrinsic-metafunctions.html new file mode 100644 index 0000000..904af36 --- /dev/null +++ b/doc/refmanual/intrinsic-metafunctions.html @@ -0,0 +1,64 @@ + + + + + + +The MPL Reference Manual: Intrinsic Metafunctions + + + + + +
Front Page / Sequences / Intrinsic Metafunctions
+
+

Intrinsic Metafunctions

+

The metafunctions that form the essential interface of sequence classes +documented in the corresponding sequence concepts are known as +intrinsic sequence operations. They differ from generic +sequence algorithms in that, in general, they need to be implemented +from scratch for each new sequence class [1].

+

It's worth noting that STL counterparts of these metafunctions are +usually implemented as member functions.

+ + + + + +
[1]In practice, many of intrinsic metafunctions offer a +default implementation that will work in majority of cases, given +that you've implemented the core functionality they rely on (such +as begin / end).
+ + + +
+ + + + + diff --git a/doc/refmanual/introspection.html b/doc/refmanual/introspection.html new file mode 100644 index 0000000..06f303c --- /dev/null +++ b/doc/refmanual/introspection.html @@ -0,0 +1,26 @@ + + + + + + +The MPL Reference Manual: Introspection + + + + + +
Front Page / Macros / Introspection
+ + + + + + diff --git a/doc/refmanual/invocation.html b/doc/refmanual/invocation.html new file mode 100644 index 0000000..105b9eb --- /dev/null +++ b/doc/refmanual/invocation.html @@ -0,0 +1,28 @@ + + + + + + +The MPL Reference Manual: Invocation + + + + + +
Front Page / Metafunctions / Invocation
+ + + + + + diff --git a/doc/refmanual/is-sequence.html b/doc/refmanual/is-sequence.html new file mode 100644 index 0000000..d00a61e --- /dev/null +++ b/doc/refmanual/is-sequence.html @@ -0,0 +1,113 @@ + + + + + + +The MPL Reference Manual: is_sequence + + + + + +
Front Page / Sequences / Intrinsic Metafunctions / is_sequence
+
+

is_sequence

+
+

Synopsis

+
+template<
+      typename X
+    >
+struct is_sequence
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a boolean Integral Constant c such that c::value == true if and +only if X is a model of Forward Sequence.

+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
XAny typeThe type to query.
+
+
+

Expression semantics

+
+typedef is_sequence<X>::type c; 
+
+ +++ + + + + + +
Return type:Boolean Integral Constant.
Semantics:

Equivalent to

+
+typedef not_< is_same< begin<T>::type,void_ > >::type c;
+
+
+
+
+

Complexity

+

Amortized constant time.

+
+ + +
+ + + + + diff --git a/doc/refmanual/iter-fold.html b/doc/refmanual/iter-fold.html new file mode 100644 index 0000000..ba57690 --- /dev/null +++ b/doc/refmanual/iter-fold.html @@ -0,0 +1,133 @@ + + + + + + +The MPL Reference Manual: iter_fold + + + + + +
Front Page / Algorithms / Iteration Algorithms / iter_fold
+
+

iter_fold

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename State
+    , typename ForwardOp
+    >
+struct iter_fold
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the result of the successive application of binary ForwardOp to the result +of the previous ForwardOp invocation (State if it's the first call) and each +iterator in the range [begin<Sequence>::type, end<Sequence>::type) in order.

+
+
+

Header

+
+#include <boost/mpl/iter_fold.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceA sequence to iterate.
StateAny typeThe initial state for the first ForwardOp +application.
ForwardOpBinary Lambda ExpressionThe operation to be executed on forward +traversal.
+
+
+

Expression semantics

+

For any Forward Sequence s, binary Lambda Expression op, and an +arbitrary type state:

+
+typedef iter_fold<s,state,op>::type t; 
+
+ +++ + + + + + +
Return type:A type.
Semantics:

Equivalent to

+
+typedef begin<Sequence>::type i1;
+typedef apply<op,state,i1>::type state1;
+typedef next<i1>::type i2;
+typedef apply<op,state1,i2>::type state2;
+...
+typedef apply<op,staten-1,in>::type staten; 
+typedef next<in>::type last; 
+typedef staten t;
+
+

where n == size<s>::value and last is identical to end<s>::type; equivalent +to typedef state t; if empty<s>::value == true.

+
+
+
+

Complexity

+

Linear. Exactly size<s>::value applications of op.

+
+
+

Example

+
+typedef vector_c<int,5,-1,0,7,2,0,-5,4> numbers;
+typedef iter_fold<
+      numbers
+    , begin<numbers>::type
+    , if_< less< deref<_1>, deref<_2> >,_2,_1 >
+    >::type max_element_iter;
+
+BOOST_MPL_ASSERT_RELATION( deref<max_element_iter>::type::value, ==, 7 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/iteration-algorithms.html b/doc/refmanual/iteration-algorithms.html new file mode 100644 index 0000000..fb4acae --- /dev/null +++ b/doc/refmanual/iteration-algorithms.html @@ -0,0 +1,47 @@ + + + + + + +The MPL Reference Manual: Iteration Algorithms + + + + + +
Front Page / Algorithms / Iteration Algorithms
+
+

Iteration Algorithms

+

Iteration algorithms are the basic building blocks behind many of the +MPL's algorithms, and are usually the first place to look at when +starting to build a new one. Abstracting away the details of sequence +iteration and employing various optimizations such as recursion +unrolling, they provide significant advantages over a hand-coded +approach.

+ + + + +
+ + + + + diff --git a/doc/refmanual/iterator-category.html b/doc/refmanual/iterator-category.html new file mode 100644 index 0000000..8dded50 --- /dev/null +++ b/doc/refmanual/iterator-category.html @@ -0,0 +1,130 @@ + + + + + + +The MPL Reference Manual: iterator_category + + + + + +
Front Page / Iterators / Iterator Metafunctions / iterator_category
+
+

iterator_category

+
+

Synopsis

+
+template<
+      typename Iterator
+    >
+struct iterator_category
+{
+    typedef typename Iterator::category type;
+};
+
+
+
+

Description

+

Returns one of the following iterator category tags:

+
    +
  • forward_iterator_tag
  • +
  • bidirectional_iterator_tag
  • +
  • random_access_iterator_tag
  • +
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
IteratorForward IteratorThe iterator to obtain a category for.
+
+
+

Expression semantics

+

For any Forward Iterators iter:

+
+typedef iterator_category<iter>::type tag; 
+
+ +++ + + + + + + + +
Return type:Integral Constant.
Semantics:tag is forward_iterator_tag if iter is a model of Forward Iterator, +bidirectional_iterator_tag if iter is a model of Bidirectional Iterator, +or random_access_iterator_tag if iter is a model of Random Access Iterator;
Postcondition:
+
forward_iterator_tag::value < bidirectional_iterator_tag::value,
+
bidirectional_iterator_tag::value < random_access_iterator_tag::value.
+
+
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+template< typename Tag, typename Iterator >
+struct algorithm_impl
+{
+    // O(n) implementation
+};
+
+template< typename Iterator >
+struct algorithm_impl<random_access_iterator_tag,Iterator>
+{
+    // O(1) implementation
+};
+
+template< typename Iterator >
+struct algorithm
+    : algorithm_impl<
+          iterator_category<Iterator>::type
+        , Iterator
+        >
+{
+};
+
+
+ +
+ + + + + diff --git a/doc/refmanual/iterator-metafunctions.html b/doc/refmanual/iterator-metafunctions.html new file mode 100644 index 0000000..a393dda --- /dev/null +++ b/doc/refmanual/iterator-metafunctions.html @@ -0,0 +1,30 @@ + + + + + + +The MPL Reference Manual: Iterator Metafunctions + + + + + +
Front Page / Iterators / Iterator Metafunctions
+ + + + + + diff --git a/doc/refmanual/iterator-range.html b/doc/refmanual/iterator-range.html new file mode 100644 index 0000000..a4f367f --- /dev/null +++ b/doc/refmanual/iterator-range.html @@ -0,0 +1,122 @@ + + + + + + +The MPL Reference Manual: iterator_range + + + + + +
Front Page / Sequences / Views / iterator_range
+
+

iterator_range

+
+

Synopsis

+
+template<
+      typename First
+    , typename Last
+    >
+struct iterator_range
+{
+    // unspecified
+    // ...
+};
+
+
+
+

Description

+

A view into subset of sequence elements identified by a pair of iterators.

+
+
+

Header

+
+#include <boost/mpl/fold.hpp>
+
+
+
+

Model of

+ +
+
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
First, +LastForward IteratorIterators identifying the view's boundaries.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Forward Sequence.

+

In the following table, v is an instance of iterator_range, first and last are +iterators into a Forward Sequence, and [first, last) form a valid range.

+ ++++ + + + + + + + + + + +
ExpressionSemantics
+iterator_range<first,last>
+iterator_range<first,last>::type
+
+
A lazy sequence all the elements in the range +[first, last).
+
+
+

Example

+
+typedef range_c<int,0,100> r;
+typedef advance_c< begin<r>::type,10 >::type first;
+typedef advance_c< end<r>::type,-10 >::type last;
+
+BOOST_MPL_ASSERT(( equal< 
+      iterator_range<first,last>
+    , range_c<int,10,90>
+    > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/iterators-concepts.html b/doc/refmanual/iterators-concepts.html new file mode 100644 index 0000000..3bdc91a --- /dev/null +++ b/doc/refmanual/iterators-concepts.html @@ -0,0 +1,43 @@ + + + + + + +The MPL Reference Manual: Concepts + + + + + +
Front Page / Iterators / Concepts
+
+

Concepts

+

All iterators in MPL are classified into three iterator concepts, or +categories, named according to the type of traversal provided. The +categories are: Forward Iterator, Bidirectional Iterator, and +Random Access Iterator. The concepts are hierarchical: +Random Access Iterator is a refinement of Bidirectional Iterator, +which, in its turn, is a refinement of Forward Iterator.

+

Because of the inherently immutable nature of the value access, MPL +iterators escape the problems of the traversal-only categorization +discussed at length in [n1550].

+ + + + + +
[n1550]http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1550.htm
+ + + +
+ + + + + diff --git a/doc/refmanual/iterators.html b/doc/refmanual/iterators.html new file mode 100644 index 0000000..bbedb19 --- /dev/null +++ b/doc/refmanual/iterators.html @@ -0,0 +1,35 @@ + + + + + + +The MPL Reference Manual: Iterators + + + + + +
Front Page / Iterators
+
+

Iterators

+

Iterators are generic means of addressing a particular element or a range +of sequential elements in a sequence. They are also a mechanism that makes +it possible to decouple algorithms from concrete compile-time sequence +implementations. Under the hood, all MPL sequence algorithms are +implemented in terms of iterators. In particular, that means that they +will work on any custom compile-time sequence, given that the appropriate +iterator inteface is provided.

+ + + + +
+ + + + + diff --git a/doc/refmanual/joint-view.html b/doc/refmanual/joint-view.html new file mode 100644 index 0000000..f1e1bae --- /dev/null +++ b/doc/refmanual/joint-view.html @@ -0,0 +1,125 @@ + + + + + + +The MPL Reference Manual: joint_view + + + + + +
Front Page / Sequences / Views / joint_view
+
+

joint_view

+
+

Synopsis

+
+template<
+      typename Sequence1
+    , typename Sequence2
+    >
+struct joint_view
+{
+    // unspecified
+    // ...
+};
+
+
+
+

Description

+

A view into the sequence of elements formed by concatenating Sequence1 +and Sequence2 elements.

+
+
+

Header

+
+#include <boost/mpl/joint_view.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
Sequence1, +Sequence2Forward SequenceSequences to create a view on.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Forward Sequence.

+

In the following table, v is an instance of joint_view, s1 and s2 are arbitrary +Forward Sequences.

+ ++++ + + + + + + + + + + + + + +
ExpressionSemantics
+joint_view<s1,s2>
+joint_view<s1,s2>::type
+
+
A lazy Forward Sequence of all the elements in the +ranges [begin<s1>::type, end<s1>::type), [begin<s2>::type, end<s2>::type).
size<v>::typeThe size of v; +size<v>::value == size<s1>::value + size<s2>::value; +linear complexity; see Forward Sequence.
+
+
+

Example

+
+typedef joint_view<
+      range_c<int,0,10>
+    , range_c<int,10,15>
+    > numbers;
+
+BOOST_MPL_ASSERT(( equal< numbers, range_c<int,0,15> > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/key-type.html b/doc/refmanual/key-type.html new file mode 100644 index 0000000..176d781 --- /dev/null +++ b/doc/refmanual/key-type.html @@ -0,0 +1,117 @@ + + + + + + +The MPL Reference Manual: key_type + + + + + +
Front Page / Sequences / Intrinsic Metafunctions / key_type
+
+

key_type

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename X
+    >
+struct key_type
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the key that would be used to identify X in Sequence.

+
+
+

Header

+
+#include <boost/mpl/key_type.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceAssociative SequenceA sequence to query.
XAny typeThe type to get the key for.
+
+
+

Expression semantics

+

For any Associative Sequence s, iterators pos1 and pos2 in s, and an +artibrary type x:

+
+typedef key_type<s,x>::type k; 
+
+ +++ + + + + + + + + + +
Return type:A type.
Precondition:x can be put in s.
Semantics:k is the key that would be used to identify x in s.
Postcondition:If key_type< s,deref<pos1>::type >::type is identical to +key_type< s,deref<pos2>::type >::type then pos1 is identical to pos2.
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef key_type< map<>,pair<int,unsigned> >::type k1;
+typedef key_type< set<>,pair<int,unsigned> >::type k2;
+
+BOOST_MPL_ASSERT(( is_same< k1,int > ));
+BOOST_MPL_ASSERT(( is_same< k2,pair<int,unsigned> > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/lambda-expression.html b/doc/refmanual/lambda-expression.html new file mode 100644 index 0000000..0900e29 --- /dev/null +++ b/doc/refmanual/lambda-expression.html @@ -0,0 +1,51 @@ + + + + + + +The MPL Reference Manual: Lambda Expression + + + + + +
Front Page / Metafunctions / Concepts / Lambda Expression
+
+

Lambda Expression

+
+

Description

+

A Lambda Expression is a compile-time invocable entity in either of the following two +forms:

+ +

Most of the MPL components accept either of those, and the concept +gives us a consice way to describe these requirements.

+
+
+

Expression requirements

+

See corresponding Metafunction Class and Placeholder Expression specifications.

+
+
+

Models

+ +
+ +
+ + + + + diff --git a/doc/refmanual/lambda.html b/doc/refmanual/lambda.html new file mode 100644 index 0000000..47399c4 --- /dev/null +++ b/doc/refmanual/lambda.html @@ -0,0 +1,146 @@ + + + + + + +The MPL Reference Manual: lambda + + + + + +
Front Page / Metafunctions / Composition and Argument Binding / lambda
+
+

lambda

+
+

Synopsis

+
+template< 
+      typename X
+    , typename Tag = unspecified
+    >
+struct lambda
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

If X is a Placeholder Expression, transforms X into a corresponding +Metafunction Class, otherwise X is returned unchanged.

+
+
+

Header

+
+#include <boost/mpl/lambda.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
XAny typeAn expression to transform.
TagAny typeA tag determining transform semantics.
+
+
+

Expression semantics

+

For arbitrary types x and tag:

+
+typedef lambda<x>::type f;
+
+ +++ + + + + + +
Return type:Metafunction Class.
Semantics:

If x is a Placeholder Expression in a general form X<a1,...an>, where +X is a class template and a1,... an are arbitrary types, equivalent +to

+
+typedef protect< bind<
+      quoten<X>
+    , lambda<a1>::type,... lambda<an>::type
+    > > f;
+
+

otherwise, f is identical to x.

+
+ +
+typedef lambda<x,tag>::type f;
+
+ +++ + + + + + +
Return type:Metafunction Class.
Semantics:

If x is a Placeholder Expression in a general form X<a1,...an>, where +X is a class template and a1,... an are arbitrary types, equivalent +to

+
+typedef protect< bind<
+      quoten<X,tag>
+    , lambda<a1,tag>::type,... lambda<an,tag>::type
+    > > f;
+
+

otherwise, f is identical to x.

+
+
+
+

Example

+
+template< typename N1, typename N2 > struct int_plus
+    : int_<( N1::value + N2::value )>
+{
+};
+
+typedef lambda< int_plus<_1, int_<42> > >::type f1;
+typedef bind< quote2<int_plus>, _1, int_<42> > f2;
+
+typedef f1::apply<42>::type r1;
+typedef f2::apply<42>::type r2;
+
+BOOST_MPL_ASSERT_RELATION( r1::value, ==, 84 );
+BOOST_MPL_ASSERT_RELATION( r2::value, ==, 84 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/less-equal.html b/doc/refmanual/less-equal.html new file mode 100644 index 0000000..aedf5f7 --- /dev/null +++ b/doc/refmanual/less-equal.html @@ -0,0 +1,132 @@ + + + + + + +The MPL Reference Manual: less_equal + + + + + +
Front Page / Metafunctions / Comparisons / less_equal
+
+

less_equal

+
+

Synopsis

+
+template<
+      typename T1
+    , typename T2
+    >
+struct less_equal
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a true-valued Integral Constant if T1 is less than or equal to T2.

+
+ + +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
T1, T2Integral ConstantOperation's arguments.
+

[Note: The requirements listed in this specification +are the ones imposed by the default implementation. See Numeric Metafunction concept +for the details on how to provide an implementation for a user-defined numeric type +that does not satisfy the Integral Constant requirements. — end note]

+
+
+

Expression semantics

+

For any Integral Constants c1 and c2:

+
+typedef less_equal<c1,c2>::type r; 
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+typedef bool_< (c1::value <= c2::value) > r;
+
+
+ +
+typedef less_equal<c1,c2> r; 
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+struct r : less_equal<c1,c2>::type {};
+
+
+
+
+

Complexity

+

Amortized constant time.

+
+ + +
+ + + + + diff --git a/doc/refmanual/less.html b/doc/refmanual/less.html new file mode 100644 index 0000000..a37d33d --- /dev/null +++ b/doc/refmanual/less.html @@ -0,0 +1,132 @@ + + + + + + +The MPL Reference Manual: less + + + + + +
Front Page / Metafunctions / Comparisons / less
+
+

less

+
+

Synopsis

+
+template<
+      typename T1
+    , typename T2
+    >
+struct less
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a true-valued Integral Constant if T1 is less than T2.

+
+
+

Header

+
+#include <boost/mpl/less.hpp>
+#include <boost/mpl/comparison.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
T1, T2Integral ConstantOperation's arguments.
+

[Note: The requirements listed in this specification +are the ones imposed by the default implementation. See Numeric Metafunction concept +for the details on how to provide an implementation for a user-defined numeric type +that does not satisfy the Integral Constant requirements. — end note]

+
+
+

Expression semantics

+

For any Integral Constants c1 and c2:

+
+typedef less<c1,c2>::type r; 
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+typedef bool_< (c1::value < c2::value) > r;
+
+
+ +
+typedef less<c1,c2> r; 
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+struct r : less<c1,c2>::type {};
+
+
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+BOOST_MPL_ASSERT(( less< int_<0>, int_<10> > ));
+BOOST_MPL_ASSERT_NOT(( less< long_<10>, int_<0> > ));
+BOOST_MPL_ASSERT_NOT(( less< long_<10>, int_<10> > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/limit-list-size.html b/doc/refmanual/limit-list-size.html new file mode 100644 index 0000000..5262e4c --- /dev/null +++ b/doc/refmanual/limit-list-size.html @@ -0,0 +1,62 @@ + + + + + + +The MPL Reference Manual: BOOST_MPL_LIMIT_LIST_SIZE + + + + + +
Front Page / Macros / Configuration / BOOST_MPL_LIMIT_LIST_SIZE
+
+

BOOST_MPL_LIMIT_LIST_SIZE

+
+

Synopsis

+
+#if !defined(BOOST_MPL_LIMIT_LIST_SIZE)
+#   define BOOST_MPL_LIMIT_LIST_SIZE \
+        implementation-defined integral constant \
+/**/
+#endif
+
+
+
+

Description

+

BOOST_MPL_LIMIT_LIST_SIZE is an overridable configuration macro regulating +the maximum arity of the list's and list_c's variadic forms. In this +implementation of the library, BOOST_MPL_LIMIT_LIST_SIZE has a default value +of 20. To override the default limit, define BOOST_MPL_LIMIT_LIST_SIZE to +the desired maximum arity rounded up to the nearest multiple of ten before +including any library header. [Note: Overriding will take effect +only if the library is configured not to use preprocessed headers. See +BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS for more information. — end note]

+
+
+

Example

+
+#define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+#define BOOST_MPL_LIMIT_LIST_SIZE 10
+#include <boost/mpl/list.hpp>
+
+using namespace boost::mpl;
+
+typedef list_c<int,1> l_1;
+typedef list_c<int,1,2,3,4,5,6,7,8,9,10> l_10;
+// typedef list_c<int,1,2,3,4,5,6,7,8,9,10,11> l_11; // error!
+
+
+ +
+ + + + + diff --git a/doc/refmanual/limit-map-size.html b/doc/refmanual/limit-map-size.html new file mode 100644 index 0000000..612375c --- /dev/null +++ b/doc/refmanual/limit-map-size.html @@ -0,0 +1,69 @@ + + + + + + +The MPL Reference Manual: BOOST_MPL_LIMIT_MAP_SIZE + + + + + +
Front Page / Macros / Configuration / BOOST_MPL_LIMIT_MAP_SIZE
+
+

BOOST_MPL_LIMIT_MAP_SIZE

+
+

Synopsis

+
+#if !defined(BOOST_MPL_LIMIT_MAP_SIZE)
+#   define BOOST_MPL_LIMIT_MAP_SIZE \
+        implementation-defined integral constant \
+/**/
+#endif
+
+
+
+

Description

+

BOOST_MPL_LIMIT_MAP_SIZE is an overridable configuration macro regulating +the maximum arity of the map's variadic form. In this +implementation of the library, BOOST_MPL_LIMIT_MAP_SIZE has a default value +of 20. To override the default limit, define BOOST_MPL_LIMIT_MAP_SIZE to +the desired maximum arity rounded up to the nearest multiple of ten before +including any library header. [Note: Overriding will take effect +only if the library is configured not to use preprocessed headers. See +BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS for more information. — end note]

+
+
+

Example

+
+#define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+#define BOOST_MPL_LIMIT_MAP_SIZE 10
+#include <boost/mpl/map.hpp>
+#include <boost/mpl/pair.hpp>
+#include <boost/mpl/int.hpp>
+
+using namespace boost::mpl;
+
+template< int i > struct ints : pair< int_<i>,int_<i> > {};
+
+typedef map< ints<1> > m_1;
+typedef map< ints<1>, ints<2>, ints<3>, ints<4>, ints<5>
+    ints<6>, ints<7>, ints<8>, ints<9>, ints<10> > m_10;
+
+// typedef map< ints<1>, ints<2>, ints<3>, ints<4>, ints<5>
+//     ints<6>, ints<7>, ints<8>, ints<9>, ints<10>, ints<11> > m_11; // error!
+
+
+ +
+ + + + + diff --git a/doc/refmanual/limit-metafunction-arity.html b/doc/refmanual/limit-metafunction-arity.html new file mode 100644 index 0000000..fc8b2b6 --- /dev/null +++ b/doc/refmanual/limit-metafunction-arity.html @@ -0,0 +1,72 @@ + + + + + + +The MPL Reference Manual: BOOST_MPL_LIMIT_METAFUNCTION_ARITY + + + + + +
Front Page / Macros / Configuration / BOOST_MPL_LIMIT_METAFUNCTION_ARITY
+
+

BOOST_MPL_LIMIT_METAFUNCTION_ARITY

+
+

Synopsis

+
+#if !defined(BOOST_MPL_LIMIT_METAFUNCTION_ARITY)
+#   define BOOST_MPL_LIMIT_METAFUNCTION_ARITY \
+        implementation-defined integral constant \
+/**/
+#endif
+
+
+
+

Description

+

BOOST_MPL_LIMIT_METAFUNCTION_ARITY is an overridable configuration macro +regulating the maximum supported arity of metafunctions and +metafunction classes. In this implementation of the +library, BOOST_MPL_LIMIT_METAFUNCTION_ARITY has a default value of 5. To +override the default limit, define BOOST_MPL_LIMIT_METAFUNCTION_ARITY to +the desired maximum arity before including any library header. +[Note: Overriding will take effect +only if the library is configured not to use preprocessed headers. See +BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS for more information. — end note]

+
+
+

Example

+
+#define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+#define BOOST_MPL_LIMIT_METAFUNCTION_ARITY 2
+#include <boost/mpl/apply.hpp>
+
+using namespace boost::mpl;
+
+template< typename T1, typename T2 > struct second
+{
+    typedef T2 type;
+};
+
+template< typename T1, typename T2, typename T3 > struct third
+{
+    typedef T3 type;
+};
+
+typedef apply< second<_1,_2_>,int,long >::type r1;
+// typedef apply< third<_1,_2_,_3>,int,long,float >::type r2; // error!
+
+
+ +
+ + + + + diff --git a/doc/refmanual/limit-set-size.html b/doc/refmanual/limit-set-size.html new file mode 100644 index 0000000..2d0b0d1 --- /dev/null +++ b/doc/refmanual/limit-set-size.html @@ -0,0 +1,62 @@ + + + + + + +The MPL Reference Manual: BOOST_MPL_LIMIT_SET_SIZE + + + + + +
Front Page / Macros / Configuration / BOOST_MPL_LIMIT_SET_SIZE
+
+

BOOST_MPL_LIMIT_SET_SIZE

+
+

Synopsis

+
+#if !defined(BOOST_MPL_LIMIT_SET_SIZE)
+#   define BOOST_MPL_LIMIT_SET_SIZE \
+        implementation-defined integral constant \
+/**/
+#endif
+
+
+
+

Description

+

BOOST_MPL_LIMIT_SET_SIZE is an overridable configuration macro regulating +the maximum arity of the set's and set_c's variadic forms. In this +implementation of the library, BOOST_MPL_LIMIT_SET_SIZE has a default value +of 20. To override the default limit, define BOOST_MPL_LIMIT_SET_SIZE to +the desired maximum arity rounded up to the nearest multiple of ten before +including any library header. [Note: Overriding will take effect +only if the library is configured not to use preprocessed headers. See +BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS for more information. — end note]

+
+
+

Example

+
+#define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+#define BOOST_MPL_LIMIT_SET_SIZE 10
+#include <boost/mpl/set.hpp>
+
+using namespace boost::mpl;
+
+typedef set_c<int,1> s_1;
+typedef set_c<int,1,2,3,4,5,6,7,8,9,10> s_10;
+// typedef set_c<int,1,2,3,4,5,6,7,8,9,10,11> s_11; // error!
+
+
+ +
+ + + + + diff --git a/doc/refmanual/limit-unrolling.html b/doc/refmanual/limit-unrolling.html new file mode 100644 index 0000000..60d2a63 --- /dev/null +++ b/doc/refmanual/limit-unrolling.html @@ -0,0 +1,52 @@ + + + + + + +The MPL Reference Manual: BOOST_MPL_LIMIT_UNROLLING + + + + + +
Front Page / Macros / Configuration / BOOST_MPL_LIMIT_UNROLLING
+
+

BOOST_MPL_LIMIT_UNROLLING

+
+

Synopsis

+
+#if !defined(BOOST_MPL_LIMIT_UNROLLING)
+#   define BOOST_MPL_LIMIT_UNROLLING \
+        implementation-defined integral constant \
+/**/
+#endif
+
+
+
+

Description

+

BOOST_MPL_LIMIT_UNROLLING is an overridable configuration macro regulating +the unrolling depth of the library's iteration algorithms. In this implementation +of the library, BOOST_MPL_LIMIT_UNROLLING has a default value of 4. To +override the default, define BOOST_MPL_LIMIT_UNROLLING to the desired +value before including any library header. +[Note: Overriding will take effect +only if the library is configured not to use preprocessed headers. See +BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS for more information. — end note]

+
+
+

Example

+

Except for overall library performace, overriding the +BOOST_MPL_LIMIT_UNROLLING's default value has no user-observable effects.

+
+ +
+ + + + + diff --git a/doc/refmanual/limit-vector-size.html b/doc/refmanual/limit-vector-size.html new file mode 100644 index 0000000..b9a02a1 --- /dev/null +++ b/doc/refmanual/limit-vector-size.html @@ -0,0 +1,62 @@ + + + + + + +The MPL Reference Manual: BOOST_MPL_LIMIT_VECTOR_SIZE + + + + + +
Front Page / Macros / Configuration / BOOST_MPL_LIMIT_VECTOR_SIZE
+
+

BOOST_MPL_LIMIT_VECTOR_SIZE

+
+

Synopsis

+
+#if !defined(BOOST_MPL_LIMIT_VECTOR_SIZE)
+#   define BOOST_MPL_LIMIT_VECTOR_SIZE \
+        implementation-defined integral constant \
+/**/
+#endif
+
+
+
+

Description

+

BOOST_MPL_LIMIT_VECTOR_SIZE is an overridable configuration macro regulating +the maximum arity of the vector's and vector_c's variadic forms. In this +implementation of the library, BOOST_MPL_LIMIT_VECTOR_SIZE has a default value +of 20. To override the default limit, define BOOST_MPL_LIMIT_VECTOR_SIZE to +the desired maximum arity rounded up to the nearest multiple of ten before +including any library header. [Note: Overriding will take effect +only if the library is configured not to use preprocessed headers. See +BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS for more information. — end note]

+
+
+

Example

+
+#define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+#define BOOST_MPL_LIMIT_VECTOR_SIZE 10
+#include <boost/mpl/vector.hpp>
+
+using namespace boost::mpl;
+
+typedef vector_c<int,1> v_1;
+typedef vector_c<int,1,2,3,4,5,6,7,8,9,10> v_10;
+// typedef vector_c<int,1,2,3,4,5,6,7,8,9,10,11> v_11; // error!
+
+
+ +
+ + + + + diff --git a/doc/refmanual/list-c.html b/doc/refmanual/list-c.html new file mode 100644 index 0000000..ee2adfe --- /dev/null +++ b/doc/refmanual/list-c.html @@ -0,0 +1,123 @@ + + + + + + +The MPL Reference Manual: list_c + + + + + +
Front Page / Sequences / Classes / list_c
+
+

list_c

+
+

Description

+

list_c is an Integral Sequence Wrapper for list. As such, it shares +all list characteristics and requirements, and differs only in the way the +original sequence content is specified.

+
+
+

Header

+ ++++ + + + + + + + + + + + + + +
Sequence formHeader
Variadic#include <boost/mpl/list_c.hpp>
Numbered#include <boost/mpl/list/listn_c.hpp>
+
+ +
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in list.

+ + ++++ + + + + + + + + + + + + + + + + +
ExpressionSemantics
+list_c<T,c1,c2,... cn>
+listn_c<T,c1,c2,... cn>
+
+
A list of integral constant wrappers +integral_c<T,c1>, +integral_c<T,c2>, ... +integral_c<T,cn>; +see Integral Sequence Wrapper.
+list_c<T,c1,c2,... cn>::type
+listn_c<T,c1,c2,... cn>::type
+
+
Identical to listn< +integral_c<T,c1>, +integral_c<T,c2>, ... +integral_c<T,cn> >; +see Integral Sequence Wrapper.
+list_c<T,c1,c2,... cn>::value_type
+listn_c<T,c1,c2,... cn>::value_type
+
+
Identical to T; see +Integral Sequence Wrapper.
+
+
+

Example

+
+typedef list_c<int,1,2,3,5,7,12,19,31> fibonacci;
+typedef push_front<fibonacci,int_<1> >::type fibonacci2;
+
+BOOST_MPL_ASSERT_RELATION( front<fibonacci2>::type::value, ==, 1 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/list.html b/doc/refmanual/list.html new file mode 100644 index 0000000..3ffc60e --- /dev/null +++ b/doc/refmanual/list.html @@ -0,0 +1,161 @@ + + + + + + +The MPL Reference Manual: list + + + + + +
Front Page / Sequences / Classes / list
+
+

list

+
+

Description

+

A list is a variadic, forward, extensible sequence of types that +supports constant-time insertion and removal of elements at the beginning, and +linear-time insertion and removal of elements at the end and in the middle.

+
+
+

Header

+ ++++ + + + + + + + + + + + + + +
Sequence formHeader
Variadic#include <boost/mpl/list.hpp>
Numbered#include <boost/mpl/list/listn.hpp>
+
+ +
+

Expression semantics

+

In the following table, l is a list, pos and last are iterators into l, +r is a Forward Sequence, and t1,t2,... tn and x are arbitrary types.

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionSemantics
+list<t1,t2,... tn>
+listn<t1,t2,... tn>
+
+
list of elements t1,t2,... tn; see +Variadic Sequence.
+list<t1,t2,... tn>::type
+listn<t1,t2,... tn>::type
+
+
Identical to listn<t1,t2,... tn>; +see Variadic Sequence.
begin<l>::typeAn iterator to the beginning of l; +see Forward Sequence.
end<l>::typeAn iterator to the end of l; +see Forward Sequence.
size<l>::typeThe size of l; see Forward Sequence.
empty<l>::typeA boolean Integral Constant c such that +c::value == true if and only if l is empty; see +Forward Sequence.
front<l>::typeThe first element in l; see +Forward Sequence.
insert<l,pos,x>::typeA new list of following elements: +[begin<l>::type, pos), x, +[pos, end<l>::type); see Extensible Sequence.
insert_range<l,pos,r>::typeA new list of following elements: +[begin<l>::type, pos), +[begin<r>::type, end<r>::type) +[pos, end<l>::type); see Extensible Sequence.
erase<l,pos>::typeA new list of following elements: +[begin<l>::type, pos), +[next<pos>::type, end<l>::type); see +Extensible Sequence.
erase<l,pos,last>::typeA new list of following elements: +[begin<l>::type, pos), +[last, end<l>::type); see Extensible Sequence.
clear<l>::typeAn empty list; see Extensible Sequence.
push_front<l,x>::typeA new list containing x as its first +element; see Front Extensible Sequence.
pop_front<l>::typeA new list containing all but the first elements +of l in the same order; see +Front Extensible Sequence.
+
+
+

Example

+
+typedef list<float,double,long double> floats;
+typedef push_front<floating_types,int>::type types;
+
+BOOST_MPL_ASSERT(( is_same< front<types>::type, int > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/logical-operations.html b/doc/refmanual/logical-operations.html new file mode 100644 index 0000000..6e5b399 --- /dev/null +++ b/doc/refmanual/logical-operations.html @@ -0,0 +1,28 @@ + + + + + + +The MPL Reference Manual: Logical Operations + + + + + +
Front Page / Metafunctions / Logical Operations
+ + + + + + diff --git a/doc/refmanual/long.html b/doc/refmanual/long.html new file mode 100644 index 0000000..9935319 --- /dev/null +++ b/doc/refmanual/long.html @@ -0,0 +1,112 @@ + + + + + + +The MPL Reference Manual: long_ + + + + + +
Front Page / Data Types / Numeric / long_
+
+

long_

+
+

Synopsis

+
+template<
+      long N
+    >
+struct long_
+{
+    // unspecified
+    // ...
+};
+
+
+
+

Description

+

An Integral Constant wrapper for long.

+
+
+

Header

+
+#include <boost/mpl/long.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
NAn integral constantA value to wrap.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Integral Constant.

+

For arbitrary integral constant n:

+ ++++ + + + + + + + + + + +
ExpressionSemantics
long_<c>An Integral Constant x such that x::value == c +and x::value_type is identical to long.
+
+
+

Example

+
+typedef long_<8> eight;
+
+BOOST_MPL_ASSERT(( is_same< eight::value_type, long > ));
+BOOST_MPL_ASSERT(( is_same< eight::type, eight > ));
+BOOST_MPL_ASSERT(( is_same< next< eight >::type, long_<9> > ));
+BOOST_MPL_ASSERT(( is_same< prior< eight >::type, long_<7> > ));
+BOOST_MPL_ASSERT_RELATION( (eight::value), ==, 8 );
+assert( eight() == 8 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/lower-bound.html b/doc/refmanual/lower-bound.html new file mode 100644 index 0000000..1d51168 --- /dev/null +++ b/doc/refmanual/lower-bound.html @@ -0,0 +1,125 @@ + + + + + + +The MPL Reference Manual: lower_bound + + + + + +
Front Page / Algorithms / Querying Algorithms / lower_bound
+
+

lower_bound

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename T
+    , typename Pred = less<_1,_2>
+    >
+struct lower_bound
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the first position in the sorted Sequence where T could be inserted without +violating the ordering.

+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceA sorted sequence to search in.
TAny typeA type to search a position for.
PredBinary Lambda ExpressionA search criteria.
+
+
+

Expression semantics

+

For any sorted Forward Sequence s, binary Lambda Expression pred, and +arbitrary type x:

+
+typedef lower_bound< s,x,pred >::type i; 
+
+ +++ + + + + + +
Return type:Forward Iterator.
Semantics:

i is the furthermost iterator in [begin<s>::type, end<s>::type) such that, for every iterator +j in [begin<s>::type, i),

+
+apply< pred, deref<j>::type, x >::type::value == true
+
+
+
+
+

Complexity

+

The number of comparisons is logarithmic: at most log2( size<s>::value ) + 1. +If s is a Random Access Sequence then the number of steps through the range +is also logarithmic; otherwise, the number of steps is proportional to +size<s>::value.

+
+
+

Example

+
+typedef vector_c<int,1,2,3,3,3,5,8> numbers;
+typedef lower_bound< numbers, int_<3> >::type iter;
+
+BOOST_MPL_ASSERT_RELATION( 
+      (distance< begin<numbers>::type,iter >::value), ==, 2
+    );
+
+BOOST_MPL_ASSERT_RELATION( deref<iter>::type::value, ==, 3 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/macros.html b/doc/refmanual/macros.html new file mode 100644 index 0000000..4e0deee --- /dev/null +++ b/doc/refmanual/macros.html @@ -0,0 +1,49 @@ + + + + + + +The MPL Reference Manual: Macros + + + + + +
Front Page / Macros
+
+

Macros

+

Being a template metaprogramming framework, the MPL concentrates on +getting one thing done well and leaves most of the clearly +preprocessor-related tasks to the corresponding specialized +libraries [PRE], [Ve03]. But whether we like it or not, macros play +an important role on today's C++ metaprogramming, and some of +the useful MPL-level functionality cannot be implemented +without leaking its preprocessor-dependent implementation +nature into the library's public interface.

+ + + + + +
[PRE]Vesa Karvonen, Paul Mensonides, +The Boost Preprocessor Metaprogramming library
+ + + + + +
[Ve03]Vesa Karvonen, The Order Programming Language, 2003.
+ + +
+ + + + + diff --git a/doc/refmanual/manual.png b/doc/refmanual/manual.png new file mode 100644 index 0000000000000000000000000000000000000000..95a0e20eec01388fcb658a4c5b643b10cca77736 GIT binary patch literal 1732 zcmeAS@N?(olHy`uVBq!ia0y~yV31~DU^v0S%)r2)w;<~o0|Ns~x}&cn1H<|g=B!;W z85kHOOI#yLg7ec#$`gxH85~pclTsBta}(23gHjVyDhp4h+AuIM7zFr)xH2#>{Qv*I zyu94S#bx*I-S6JLyLl#Qw%kQ8fkuhZRK%XU?49 z5oO>|P&sn?*ueuQ4;^5g&J5xmJjGSQudXcZ!=TVGLC{{FnOU6M+`fljz~P601B2r1 zlRT^jj13GJ;l3Jntk__dX}B@VDKFmXiowX%ltL4&U8Mj}rGgOgZtlLY5?Ymle&-2BYk#KPR< zz@AnN6JxV;<16z6g~-BXm1S;v3A@@NIRqR|{HnO{iP?cc@%HgkM-Ci1c8=L!n1Qk7 zjh~;{0yQ_c9Uxb+G9I2hpL3!qBQ(NN`5hP@YF9HbaVQ=?-8!$Ifr%qeOQdcUmh06UWJViHA%A4nGdDDl|OUDZ_c-2(HBOMTytaoPkBa z=n<0}6SFyYjF>{h1m%v2(`Qd?>=&KK#>m9M$#}X@%`HHbi94@>!Rai&f~CtWb`FIr ze;6h`ZdzX1z~FR}U&g_bFRbDwmwq7Q@IQuy2=yLW99;dzX7GkhF7wOF)f{&*cpxivY8i3&Yz- zt}Uhx3=6k(&S=OK(ClMi;;@X_aq*I#1H(h_&kT$$EBPmeGca-7wJTF|vE&zUIMKm= z$)>rQNueR&mDz&-GbZRTb0~!T4qya%#$AH}B%UdErGlM9p$3$+f82^>U~J)MWD%&^ zmG;0ngPB9&%O5_S9S>KsDKr?I;$#!6_${o^U~pR8uEK_aMPQ!=6Nkc?Pd(!EK*?yY z%#+8iDzyy^PAiYza9G$hfr&#QV#bC7gMxyFCN@t2g@y@I9TL4#4Gc|7qul(|%*?i! z@C!J6IC7{fQXUim??GCMFl z>}GFZI3&)`z}Pa;Wnu*bV~gsIhmPz54m=)>XAdzhOmt#kY&o%IjZRO_8<_(e8l|}f z96V&z+4$TRsHwH^Gca*1ee@vZiAx`M1B27VsDmYWxli3zryg z(cwlna)*qxfkQ(jt7Qx*h$@&^1ngKK#zKN6UEYB~@q7P;$BYUM0lT$)G;Yc&Gz3Ix z9H>Zo`mDL#+<_snB;$s_H%1l#w~1$aHKsE#aUAvYSk80rHY10^m3Ly?UCE&Q8o?af zc+Z!aL!srr!C_W~h7YaW(3A~IBXB!GNu8ho8$bP0l+XkK DDp@<{ literal 0 HcmV?d00001 diff --git a/doc/refmanual/map.html b/doc/refmanual/map.html new file mode 100644 index 0000000..f5db382 --- /dev/null +++ b/doc/refmanual/map.html @@ -0,0 +1,183 @@ + + + + + + +The MPL Reference Manual: map + + + + + +
Front Page / Sequences / Classes / map
+
+

map

+
+

Description

+

map is a variadic, associative, extensible sequence of type pairs that +supports constant-time insertion and removal of elements, and testing for membership. +A map may contain at most one element for each key.

+
+
+

Header

+ ++++ + + + + + + + + + + + + + +
Sequence formHeader
Variadic#include <boost/mpl/map.hpp>
Numbered#include <boost/mpl/map/mapn.hpp>
+
+ +
+

Expression semantics

+

In the following table and subsequent specifications, m is an instance of map, +pos is an iterator into m, x and p1,p2,... pn are pairs, and k is an arbitrary type.

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionSemantics
+map<p1,p2,... pn>
+mapn<p1,p2,... pn>
+
+
map of elements p1,p2,... pn; see +Variadic Sequence.
+map<p1,p2,... pn>::type
+mapn<p1,p2,... pn>::type
+
+
Identical to mapn<p1,p2,... pn>; +see Variadic Sequence.
begin<m>::typeAn iterator pointing to the beginning of m; +see Associative Sequence.
end<m>::typeAn iterator pointing to the end of m; +see Associative Sequence.
size<m>::typeThe size of m; see Associative Sequence.
empty<m>::typeA boolean Integral Constant c such that +c::value == true if and only if m is empty; see +Associative Sequence.
front<m>::typeThe first element in m; see +Associative Sequence.
has_key<m,k>::typeQueries the presence of elements with the key k in +m; see Associative Sequence.
count<m,k>::typeThe number of elements with the key k in m; +see Associative Sequence.
order<m,k>::typeA unique unsigned Integral Constant associated with +the key k in m; see Associative Sequence.
+at<m,k>::type
+at<m,k,default>::type
+
+
The element associated with the key k in +m; see Associative Sequence.
key_type<m,x>::typeIdentical to x::first; see Associative Sequence.
value_type<m,x>::typeIdentical to x::second; see Associative Sequence.
insert<m,x>::type

A new map equivalent to m except that

+
+at< t, key_type<m,x>::type >::type
+
+

is identical to value_type<m,x>::type.

+
insert<m,pos,x>::typeEquivalent to insert<m,x>::type; pos is ignored.
erase_key<m,k>::typeA new map equivalent to m except that +has_key<t, k>::value == false.
erase<m,pos>::typeEquivalent to erase<m, deref<pos>::type >::type.
clear<m>::typeAn empty map; see clear.
+
+
+

Example

+
+typedef map<
+      pair<int,unsigned>
+    , pair<char,unsigned char>
+    , pair<long_<5>,char[17]>
+    , pair<int[42],bool>
+    > m;
+
+BOOST_MPL_ASSERT_RELATION( size<m>::value, ==, 4 );
+BOOST_MPL_ASSERT_NOT(( empty<m> ));
+
+BOOST_MPL_ASSERT(( is_same< at<m,int>::type, unsigned > ));
+BOOST_MPL_ASSERT(( is_same< at<m,long_<5> >::type, char[17] > ));
+BOOST_MPL_ASSERT(( is_same< at<m,int[42]>::type, bool > ));
+BOOST_MPL_ASSERT(( is_same< at<m,long>::type, void_ > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/max-element.html b/doc/refmanual/max-element.html new file mode 100644 index 0000000..760c76b --- /dev/null +++ b/doc/refmanual/max-element.html @@ -0,0 +1,114 @@ + + + + + + +The MPL Reference Manual: max_element + + + + + +
Front Page / Algorithms / Querying Algorithms / max_element
+
+

max_element

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename Pred = less<_1,_2>
+    >
+struct max_element
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns an iterator to the largest element in Sequence.

+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceA sequence to be searched.
PredBinary Lambda ExpressionA comparison criteria.
+
+
+

Expression semantics

+

For any Forward Sequence s and binary Lambda Expression pred:

+
+typedef max_element<s,pred>::type i; 
+
+ +++ + + + + + +
Return type:Forward Iterator.
Semantics:

i is the first iterator in [begin<s>::type, end<s>::type) such that for every iterator j +in [begin<s>::type, end<s>::type),

+
+apply< pred, deref<i>::type, deref<j>::type >::type::value == false
+
+
+
+
+

Complexity

+

Linear. Zero comparisons if s is empty, otherwise exactly size<s>::value - 1 +comparisons.

+
+
+

Example

+
+typedef vector<bool,char[50],long,double> types;
+typedef max_element<
+      transform_view< types,sizeof_<_1> >
+    >::type iter;
+
+BOOST_MPL_ASSERT(( is_same< deref<iter::base>::type, char[50]> ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/max.html b/doc/refmanual/max.html new file mode 100644 index 0000000..8f87fe0 --- /dev/null +++ b/doc/refmanual/max.html @@ -0,0 +1,115 @@ + + + + + + +The MPL Reference Manual: max + + + + + +
Front Page / Metafunctions / Miscellaneous / max
+
+

max

+
+

Synopsis

+
+template<
+      typename N1
+    , typename N2
+    >
+struct max
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the larger of its two arguments.

+
+
+

Header

+
+#include <boost/mpl/min_max.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
N1, N2Any typeTypes to compare.
+
+
+

Expression semantics

+

For arbitrary types x and y:

+
+typedef max<x,y>::type r;
+
+ +++ + + + + + + + +
Return type:A type.
Precondition:less<x,y>::value is a well-formed integral constant expression.
Semantics:

Equivalent to

+
+typedef if_< less<x,y>,y,x >::type r;
+
+
+
+
+

Complexity

+

Constant time.

+
+
+

Example

+
+typedef fold<
+      vector_c<int,1,7,0,-2,5,-1>
+    , int_<10>
+    , max<_1,_2>
+    >::type r;
+
+BOOST_MPL_ASSERT(( is_same< r, int_<10> > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/metafunction-class.html b/doc/refmanual/metafunction-class.html new file mode 100644 index 0000000..de709dc --- /dev/null +++ b/doc/refmanual/metafunction-class.html @@ -0,0 +1,121 @@ + + + + + + +The MPL Reference Manual: Metafunction Class + + + + + +
Front Page / Metafunctions / Concepts / Metafunction Class
+
+

Metafunction Class

+
+

Summary

+

A metafunction class is a certain form of metafunction representation +that enables higher-order metaprogramming. More precisely, it's a class +with a publicly-accessible nested Metafunction called apply. +Correspondingly, a metafunction class invocation is defined as invocation +of its nested apply metafunction.

+
+
+

Expression requirements

+

In the following table and subsequent specifications, f is a Metafunction Class.

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ExpressionTypeComplexity
f::apply::typeAny typeUnspecified.
f::apply<>::typeAny typeUnspecified.
f::apply<a1,...an>::typeAny typeUnspecified.
+
+
+

Expression semantics

+
+typedef f::apply::type x;
+
+ +++ + + + + + +
Precondition:f is a nullary Metafunction Class; f::apply::type is a type-name.
Semantics:x is the result of the metafunction class invocation.
+ +
+typedef f::apply<>::type x;
+
+ +++ + + + + + +
Precondition:f is a nullary Metafunction Class; f::apply<>::type is a type-name.
Semantics:x is the result of the metafunction class invocation.
+ +
+typedef f::apply<a1,...an>::type x;
+
+ +++ + + + + + +
Precondition:f is an n-ary metafunction class; apply is a Metafunction.
Semantics:x is the result of the metafunction class +invocation with the actual arguments a1,... an.
+
+ + +
+ + + + + diff --git a/doc/refmanual/metafunction.html b/doc/refmanual/metafunction.html new file mode 100644 index 0000000..bdd250f --- /dev/null +++ b/doc/refmanual/metafunction.html @@ -0,0 +1,127 @@ + + + + + + +The MPL Reference Manual: Metafunction + + + + + +
Front Page / Metafunctions / Concepts / Metafunction
+
+

Metafunction

+
+

Description

+

A metafunction is a class or a class template that represents a +function invocable at compile-time. An non-nullary metafunction is +invoked by instantiating the class template with particular +template parameters (metafunction arguments); the result of the +metafunction application is accessible through the instantiation's +nested type typedef. All metafunction's arguments must be types +(i.e. only type template parameters are allowed). A metafunction +can have a variable number of parameters. A nullary metafunction is +represented as a (template) class with a nested type typename +member.

+
+
+

Expression requirements

+

In the following table and subsequent specifications, f is a Metafunction.

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ExpressionTypeComplexity
f::typeAny typeUnspecified.
f<>::typeAny typeUnspecified.
f<a1,..,an>::typeAny typeUnspecified.
+
+
+

Expression semantics

+
+typedef f::type x;
+
+ +++ + + + + + +
Precondition:f is a nullary Metafunction; f::type is a type-name.
Semantics:x is the result of the metafunction invocation.
+ +
+typedef f<>::type x;
+
+ +++ + + + + + +
Precondition:f is a nullary Metafunction; f<>::type is a type-name.
Semantics:x is the result of the metafunction invocation.
+ +
+typedef f<a1,... an>::type x;
+
+ +++ + + + + + +
Precondition:f is an n-ary Metafunction; a1,... an are types; +f<a1,...an>::type is a type-name.
Semantics:x is the result of the metafunction invocation +with the actual arguments a1,... an.
+
+ + +
+ + + + + diff --git a/doc/refmanual/metafunctions-concepts.html b/doc/refmanual/metafunctions-concepts.html new file mode 100644 index 0000000..27a6bbf --- /dev/null +++ b/doc/refmanual/metafunctions-concepts.html @@ -0,0 +1,31 @@ + + + + + + +The MPL Reference Manual: Concepts + + + + + +
Front Page / Metafunctions / Concepts
+ + + + + + diff --git a/doc/refmanual/metafunctions.html b/doc/refmanual/metafunctions.html new file mode 100644 index 0000000..5160904 --- /dev/null +++ b/doc/refmanual/metafunctions.html @@ -0,0 +1,82 @@ + + + + + + +The MPL Reference Manual: Metafunctions + + + + + +
Front Page / Metafunctions
+
+

Metafunctions

+

The MPL includes a number of predefined metafunctions that can be roughly +classified in two categories: general purpose metafunctions, dealing with +conditional type selection and higher-order metafunction invocation, +composition, and argument binding, and numeric metafunctions, +incapsulating built-in and user-defined arithmetic, comparison, +logical, and bitwise operations.

+

Given that it is possible to perform integer numeric computations at +compile time using the conventional operators notation, the need for the +second category might be not obvious, but it in fact plays a cental role in +making programming with MPL seemingly effortless. In +particular, there are at least two contexts where built-in language +facilities fall short [3]:

+
    +
  1. Passing a computation to an algorithm.
  2. +
  3. Performing a computation on non-integer data.
  4. +
+

The second use case deserves special attention. In contrast to the built-in, +strictly integer compile-time arithmetics, the MPL numeric metafunctions are +polymorphic, with support for mixed-type arithmetics. This means that they +can operate on a variety of numeric types — for instance, rational, +fixed-point or complex numbers, — and that, in general, you are allowed to +freely intermix these types within a single expression. See Numeric Metafunction concept for more details on the MPL numeric infrastructure.

+ +

To reduce a negative syntactical impact of the metafunctions notation +over the infix operator notation, all numeric metafunctions +allow to pass up to N arguments, where N is defined by the value of +BOOST_MPL_LIMIT_METAFUNCTION_ARITY configuration macro.

+ + + + + +
[3]All other considerations aside, as of the time of this writing +(early 2004), using built-in operators on integral constants still often +present a portability problem — many compilers cannot handle particular +forms of expressions, forcing us to use conditional compilation. Because MPL +numeric metafunctions work on types and encapsulate these kind of workarounds +internally, they elude these problems, so if you aim for portability, it is +generally adviced to use them in the place of the conventional operators, even +at the price of slightly decreased readability.
+ + +
+ + + + + diff --git a/doc/refmanual/min-element.html b/doc/refmanual/min-element.html new file mode 100644 index 0000000..bee4920 --- /dev/null +++ b/doc/refmanual/min-element.html @@ -0,0 +1,114 @@ + + + + + + +The MPL Reference Manual: min_element + + + + + +
Front Page / Algorithms / Querying Algorithms / min_element
+
+

min_element

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename Pred = less<_1,_2>
+    >
+struct min_element
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns an iterator to the smallest element in Sequence.

+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceA sequence to be searched.
PredBinary Lambda ExpressionA comparison criteria.
+
+
+

Expression semantics

+

For any Forward Sequence s and binary Lambda Expression pred:

+
+typedef min_element<s,pred>::type i; 
+
+ +++ + + + + + +
Return type:Forward Iterator.
Semantics:

i is the first iterator in [begin<s>::type, end<s>::type) such that for every iterator j +in [begin<s>::type, end<s>::type),

+
+apply< pred, deref<j>::type, deref<i>::type >::type::value == false
+
+
+
+
+

Complexity

+

Linear. Zero comparisons if s is empty, otherwise exactly size<s>::value - 1 +comparisons.

+
+
+

Example

+
+typedef vector<bool,char[50],long,double> types;
+typedef min_element<
+      transform_view< types,sizeof_<_1> >
+    >::type iter;
+
+BOOST_MPL_ASSERT(( is_same< deref<iter::base>::type, bool> ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/min.html b/doc/refmanual/min.html new file mode 100644 index 0000000..c6611f2 --- /dev/null +++ b/doc/refmanual/min.html @@ -0,0 +1,115 @@ + + + + + + +The MPL Reference Manual: min + + + + + +
Front Page / Metafunctions / Miscellaneous / min
+
+

min

+
+

Synopsis

+
+template<
+      typename N1
+    , typename N2
+    >
+struct min
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the smaller of its two arguments.

+
+
+

Header

+
+#include <boost/mpl/min_max.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
N1, N2Any typeTypes to compare.
+
+
+

Expression semantics

+

For arbitrary types x and y:

+
+typedef min<x,y>::type r;
+
+ +++ + + + + + + + +
Return type:A type.
Precondition:less<x,y>::value is a well-formed integral constant expression.
Semantics:

Equivalent to

+
+typedef if_< less<x,y>,x,y >::type r;
+
+
+
+
+

Complexity

+

Constant time.

+
+
+

Example

+
+typedef fold<
+      vector_c<int,1,7,0,-2,5,-1>
+    , int_<-10>
+    , min<_1,_2>
+    >::type r;
+
+BOOST_MPL_ASSERT(( is_same< r, int_<-10> > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/minus.html b/doc/refmanual/minus.html new file mode 100644 index 0000000..fde14b3 --- /dev/null +++ b/doc/refmanual/minus.html @@ -0,0 +1,140 @@ + + + + + + +The MPL Reference Manual: minus + + + + + +
Front Page / Metafunctions / Arithmetic Operations / minus
+
+

minus

+
+

Synopsis

+
+template<
+      typename T1
+    , typename T2
+    , typename T3 = unspecified
+    ...
+    , typename Tn = unspecified
+    >
+struct minus
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the difference of its arguments.

+
+
+

Header

+
+#include <boost/mpl/minus.hpp>
+#include <boost/mpl/arithmetic.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
T1, T2,... TnIntegral ConstantOperation's arguments.
+

[Note: The requirements listed in this specification +are the ones imposed by the default implementation. See Numeric Metafunction concept +for the details on how to provide an implementation for a user-defined numeric type +that does not satisfy the Integral Constant requirements. — end note]

+
+
+

Expression semantics

+

For any Integral Constants c1,c2,... cn:

+
+typedef minus<c1,...cn>::type r; 
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+typedef integral_c<
+      typeof(c1::value - c2::value)
+    , ( c1::value - c2::value )
+    > c;
+    
+typedef minus<c,c3,...cn>::type r; 
+
+
+ +
+typedef minus<c1,...cn> r;
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+struct r : minus<c1,...cn>::type {};
+
+
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef minus< int_<-10>, int_<3>, long_<1> >::type r;
+BOOST_MPL_ASSERT_RELATION( r::value, ==, -14 );
+BOOST_MPL_ASSERT(( is_same< r::value_type, long > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/miscellaneous.html b/doc/refmanual/miscellaneous.html new file mode 100644 index 0000000..0f2174d --- /dev/null +++ b/doc/refmanual/miscellaneous.html @@ -0,0 +1,32 @@ + + + + + + +The MPL Reference Manual: Miscellaneous + + + + + +
Front Page / Metafunctions / Miscellaneous
+ + + + + + diff --git a/doc/refmanual/modulus.html b/doc/refmanual/modulus.html new file mode 100644 index 0000000..4b5a649 --- /dev/null +++ b/doc/refmanual/modulus.html @@ -0,0 +1,139 @@ + + + + + + +The MPL Reference Manual: modulus + + + + + +
Front Page / Metafunctions / Arithmetic Operations / modulus
+
+

modulus

+
+

Synopsis

+
+template<
+      typename T1
+    , typename T2
+    >
+struct modulus
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the modulus of its arguments.

+
+ + +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
T1, T2Integral ConstantOperation's arguments.
+

[Note: The requirements listed in this specification +are the ones imposed by the default implementation. See Numeric Metafunction concept +for the details on how to provide an implementation for a user-defined numeric type +that does not satisfy the Integral Constant requirements. — end note]

+
+
+

Expression semantics

+

For any Integral Constants c1 and c2:

+
+typedef modulus<c1,c2>::type r;
+
+ +++ + + + + + + + +
Return type:Integral Constant.
Precondition:c2::value != 0
Semantics:

Equivalent to

+
+typedef integral_c<
+      typeof(c1::value % c2::value)
+    , ( c1::value % c2::value )
+    > r;
+
+
+ +
+typedef modulus<c1,c2> r;
+
+ +++ + + + + + + + +
Return type:Integral Constant.
Precondition:c2::value != 0
Semantics:

Equivalent to

+
+struct r : modulus<c1,c2>::type {};
+
+
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef modulus< int_<10>, long_<3> >::type r;
+BOOST_MPL_ASSERT_RELATION( r::value, ==, 1 );
+BOOST_MPL_ASSERT(( is_same< r::value_type, long > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/negate.html b/doc/refmanual/negate.html new file mode 100644 index 0000000..6c39141 --- /dev/null +++ b/doc/refmanual/negate.html @@ -0,0 +1,130 @@ + + + + + + +The MPL Reference Manual: negate + + + + + +
Front Page / Metafunctions / Arithmetic Operations / negate
+
+

negate

+
+

Synopsis

+
+template<
+      typename T
+    >
+struct negate
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the negative (additive inverse) of its argument.

+
+ + +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
TIntegral ConstantOperation's argument.
+

[Note: The requirements listed in this specification +are the ones imposed by the default implementation. See Numeric Metafunction concept +for the details on how to provide an implementation for a user-defined numeric type +that does not satisfy the Integral Constant requirements. — end note]

+
+
+

Expression semantics

+

For any Integral Constant c:

+
+typedef negate<c>::type r; 
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+typedef integral_c< c::value_type, ( -c::value ) > r;
+
+
+ +
+typedef negate<c> r; 
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+struct r : negate<c>::type {};
+
+
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef negate< int_<-10> >::type r;
+BOOST_MPL_ASSERT_RELATION( r::value, ==, 10 );
+BOOST_MPL_ASSERT(( is_same< r::value_type, int > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/next.html b/doc/refmanual/next.html new file mode 100644 index 0000000..f3b5470 --- /dev/null +++ b/doc/refmanual/next.html @@ -0,0 +1,115 @@ + + + + + + +The MPL Reference Manual: next + + + + + +
Front Page / Iterators / Iterator Metafunctions / next
+ + + + + + diff --git a/doc/refmanual/not-equal-to.html b/doc/refmanual/not-equal-to.html new file mode 100644 index 0000000..2cb1a07 --- /dev/null +++ b/doc/refmanual/not-equal-to.html @@ -0,0 +1,131 @@ + + + + + + +The MPL Reference Manual: not_equal_to + + + + + +
Front Page / Metafunctions / Comparisons / not_equal_to
+
+

not_equal_to

+
+

Synopsis

+
+template<
+      typename T1
+    , typename T2
+    >
+struct not_equal_to
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a true-valued Integral Constant if T1 and T2 are not equal.

+
+ + +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
T1, T2Integral ConstantOperation's arguments.
+

[Note: The requirements listed in this specification +are the ones imposed by the default implementation. See Numeric Metafunction concept +for the details on how to provide an implementation for a user-defined numeric type +that does not satisfy the Integral Constant requirements. — end note]

+
+
+

Expression semantics

+

For any Integral Constants c1 and c2:

+
+typedef not_equal_to<c1,c2>::type r; 
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+typedef bool_< (c1::value != c2::value) > r;
+
+
+ +
+typedef not_equal_to<c1,c2> r; 
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+struct r : not_equal_to<c1,c2>::type {};
+
+
+
+
+

Complexity

+

Amortized constant time.

+
+ + +
+ + + + + diff --git a/doc/refmanual/not.html b/doc/refmanual/not.html new file mode 100644 index 0000000..782e175 --- /dev/null +++ b/doc/refmanual/not.html @@ -0,0 +1,117 @@ + + + + + + +The MPL Reference Manual: not_ + + + + + +
Front Page / Metafunctions / Logical Operations / not_
+
+

not_

+
+

Synopsis

+
+template< 
+      typename F
+    >
+struct not_
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the result of logical not (!) operation on its argument.

+
+
+

Header

+
+#include <boost/mpl/not.hpp>
+#include <boost/mpl/logical.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
FNullary MetafunctionOperation's argument.
+
+
+

Expression semantics

+

For arbitrary nullary Metafunction f:

+
+typedef not_<f>::type r;
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+typedef bool_< (!f::type::value) > r;
+
+
+ +
+typedef not_<f> r;
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+struct r : not_<f>::type {};
+
+
+
+
+

Example

+
+BOOST_MPL_ASSERT_NOT(( not_< true_ > ));
+BOOST_MPL_ASSERT(( not_< false_ > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/numeric-cast.html b/doc/refmanual/numeric-cast.html new file mode 100644 index 0000000..b364e57 --- /dev/null +++ b/doc/refmanual/numeric-cast.html @@ -0,0 +1,149 @@ + + + + + + +The MPL Reference Manual: numeric_cast + + + + + +
Front Page / Metafunctions / Miscellaneous / numeric_cast
+
+

numeric_cast

+
+

Synopsis

+
+template< 
+      typename SourceTag
+    , typename TargetTag
+    >
+struct numeric_cast;
+
+
+
+

Description

+

Each numeric_cast specialization is a user-specialized unary Metafunction Class +providing a conversion between two numeric types.

+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SourceTagIntegral ConstantA tag for the conversion's source type.
TargetTagIntegral ConstantA tag for the conversion's destination type.
+
+
+

Expression semantics

+

If x and y are two numeric types, x is convertible to y, and +x_tag and y_tag are the types' corresponding Integral Constant tags:

+
+typedef apply_wrap2< numeric_cast<x_tag,y_tag>,x >::type  r;
+
+ +++ + + + + + +
Return type:A type.
Semantics:r is a value of x converted to the type of y.
+
+
+

Complexity

+

Unspecified.

+
+
+

Example

+
+struct complex_tag : int_<10> {};
+
+template< typename Re, typename Im > struct complex
+{
+    typedef complex_tag tag;
+    typedef complex type;
+    typedef Re real;
+    typedef Im imag;
+};
+
+template< typename C > struct real : C::real {};
+template< typename C > struct imag : C::imag {};
+
+namespace boost { namespace mpl {
+
+template<> struct numeric_cast< integral_c_tag,complex_tag >
+{
+    template< typename N > struct apply
+        : complex< N, integral_c< typename N::value_type, 0 > >
+    {
+    };
+};
+
+template<>
+struct plus_impl< complex_tag,complex_tag >
+{
+    template< typename N1, typename N2 > struct apply
+        : complex<
+              plus< typename N1::real, typename N2::real >
+            , plus< typename N1::imag, typename N2::imag >
+            >
+    {
+    };
+};
+
+}}
+
+typedef int_<2> i;
+typedef complex< int_<5>, int_<-1> > c1;
+typedef complex< int_<-5>, int_<1> > c2;
+
+typedef plus<c1,i> r4;
+BOOST_MPL_ASSERT_RELATION( real<r4>::value, ==, 7 );
+BOOST_MPL_ASSERT_RELATION( imag<r4>::value, ==, -1 );
+
+typedef plus<i,c2> r5;
+BOOST_MPL_ASSERT_RELATION( real<r5>::value, ==, -3 );
+BOOST_MPL_ASSERT_RELATION( imag<r5>::value, ==, 1 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/numeric-metafunction.html b/doc/refmanual/numeric-metafunction.html new file mode 100644 index 0000000..8a30897 --- /dev/null +++ b/doc/refmanual/numeric-metafunction.html @@ -0,0 +1,171 @@ + + + + + + +The MPL Reference Manual: Numeric Metafunction + + + + + +
Front Page / Metafunctions / Concepts / Numeric Metafunction
+
+

Numeric Metafunction

+
+

Description

+

A Numeric Metafunction is a Tag Dispatched Metafunction that provides +a built-in infrastructure for easy implementation of mixed-type operations.

+
+
+

Expression requirements

+

In the following table and subsequent specifications, op is a placeholder token for the actual +Numeric Metafunction's name, and x, y and x1,x2,... xn are +arbitrary numeric types.

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ExpressionTypeComplexity
op_tag<x>::typeIntegral ConstantAmortized constant time.
+op_impl<
+     op_tag<x>::type
+   , op_tag<y>::type
+   >::apply<x,y>::type
+
+
Any typeUnspecified.
op<x1,x2,... xn>::typeAny typeUnspecified.
+
+
+

Expression semantics

+
+typedef op_tag<x>::type tag;
+
+ +++ + + + +
Semantics:tag is a tag type for x for op. +tag::value is x's conversion rank.
+ +
+typedef op_impl<
+      op_tag<x>::type
+    , op_tag<y>::type
+    >::apply<x,y>::type r;
+
+ +++ + + + +
Semantics:r is the result of op application on arguments x +and y.
+ +
+typedef op<x1,x2,... xn>::type r;
+
+ +++ + + + +
Semantics:r is the result of op application on arguments x1,x2,... xn.
+
+
+

Example

+
+struct complex_tag : int_<10> {};
+
+template< typename Re, typename Im > struct complex
+{
+    typedef complex_tag tag;
+    typedef complex type;
+    typedef Re real;
+    typedef Im imag;
+};
+
+template< typename C > struct real : C::real {};
+template< typename C > struct imag : C::imag {};
+
+namespace boost { namespace mpl {
+
+template<>
+struct plus_impl< complex_tag,complex_tag >
+{
+    template< typename N1, typename N2 > struct apply
+        : complex<
+              plus< typename N1::real, typename N2::real >
+            , plus< typename N1::imag, typename N2::imag >
+            >
+    {
+    };
+};
+
+}}
+
+typedef complex< int_<5>, int_<-1> > c1;
+typedef complex< int_<-5>, int_<1> > c2;
+
+typedef plus<c1,c2> r1;
+BOOST_MPL_ASSERT_RELATION( real<r1>::value, ==, 0 );
+BOOST_MPL_ASSERT_RELATION( imag<r1>::value, ==, 0 );
+
+typedef plus<c1,c1> r2;
+BOOST_MPL_ASSERT_RELATION( real<r2>::value, ==, 10 );
+BOOST_MPL_ASSERT_RELATION( imag<r2>::value, ==, -2 );
+
+typedef plus<c2,c2> r3;
+BOOST_MPL_ASSERT_RELATION( real<r3>::value, ==, -10 );
+BOOST_MPL_ASSERT_RELATION( imag<r3>::value, ==, 2 );
+
+
+ + +
+ + + + + diff --git a/doc/refmanual/numeric.html b/doc/refmanual/numeric.html new file mode 100644 index 0000000..5000678 --- /dev/null +++ b/doc/refmanual/numeric.html @@ -0,0 +1,29 @@ + + + + + + +The MPL Reference Manual: Numeric + + + + + +
Front Page / Data Types / Numeric
+ + + + + + diff --git a/doc/refmanual/or.html b/doc/refmanual/or.html new file mode 100644 index 0000000..37e0066 --- /dev/null +++ b/doc/refmanual/or.html @@ -0,0 +1,126 @@ + + + + + + +The MPL Reference Manual: or_ + + + + + +
Front Page / Metafunctions / Logical Operations / or_
+
+

or_

+
+

Synopsis

+
+template< 
+      typename F1
+    , typename F2
+    ...
+    , typename Fn = unspecified
+    >
+struct or_
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the result of short-circuit logical or (||) operation on its arguments.

+
+
+

Header

+
+#include <boost/mpl/or.hpp>
+#include <boost/mpl/logical.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
F1, F2,... FnNullary MetafunctionOperation's arguments.
+
+
+

Expression semantics

+

For arbitrary nullary Metafunctions f1, f2,... fn:

+
+typedef or_<f1,f2,...,fn>::type r;
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:r is true_ if either of f1::type::value, f2::type::value,... +fn::type::value expressions evaluates to true, and false_ otherwise; +guarantees left-to-right evaluation; the operands subsequent to the first +fi metafunction that evaluates to true are not evaluated.
+ +
+typedef or_<f1,f2,...,fn> r;
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+struct r : or_<f1,f2,...,fn>::type {};
+
+
+
+
+

Example

+
+struct unknown;
+
+BOOST_MPL_ASSERT(( or_< true_,true_ > ));
+BOOST_MPL_ASSERT(( or_< false_,true_ > ));
+BOOST_MPL_ASSERT(( or_< true_,false_ > ));
+BOOST_MPL_ASSERT_NOT(( or_< false_,false_ > ));
+BOOST_MPL_ASSERT(( or_< true_,unknown > )); // OK
+BOOST_MPL_ASSERT(( or_< true_,unknown,unknown > )); // OK too
+
+
+ +
+ + + + + diff --git a/doc/refmanual/order.html b/doc/refmanual/order.html new file mode 100644 index 0000000..bf96030 --- /dev/null +++ b/doc/refmanual/order.html @@ -0,0 +1,113 @@ + + + + + + +The MPL Reference Manual: order + + + + + +
Front Page / Sequences / Intrinsic Metafunctions / order
+
+

order

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename Key
+    >
+struct order
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a unique unsigned Integral Constant associated with the key Key in +Sequence.

+
+
+

Header

+
+#include <boost/mpl/order.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceAssociative SequenceA sequence to query.
KeyAny typeThe queried key.
+
+
+

Expression semantics

+

For any Associative Sequence s, and arbitrary type key:

+
+typedef order<s,key>::type n; 
+
+ +++ + + + + + +
Return type:Unsigned Integral Constant.
Semantics:If has_key<s,key>::value == true, n is a unique unsigned +Integral Constant associated with key in s; otherwise, +n is identical to void_.
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef map< pair<int,unsigned>, pair<char,long> > m;
+
+BOOST_MPL_ASSERT_NOT(( is_same< order<m,int>::type, void_ > ));
+BOOST_MPL_ASSERT(( is_same< order<m,long>::type,void_ > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/pair.html b/doc/refmanual/pair.html new file mode 100644 index 0000000..67c94c5 --- /dev/null +++ b/doc/refmanual/pair.html @@ -0,0 +1,74 @@ + + + + + + +The MPL Reference Manual: pair + + + + + +
Front Page / Data Types / Miscellaneous / pair
+
+

pair

+
+

Synopsis

+
+template<
+      typename T1
+    , typename T2
+    >
+struct pair
+{
+    typedef pair type;
+    typedef T1 first;
+    typedef T2 second;
+};
+
+
+
+

Description

+

A transparent holder for two arbitrary types.

+
+
+

Header

+
+#include <boost/mpl/pair.hpp>
+
+
+
+

Example

+

Count a number of elements in the sequence together with a number of negative +elements among these.

+
+typedef fold<
+      vector_c<int,-1,0,5,-7,-2,4,5,7>
+    , pair< int_<0>, int_<0> >
+    , pair< 
+          next< first<_1> >
+        , if_< 
+              less< _2, int_<0> >
+            , next< second<_1> >
+            , second<_1> 
+            >
+        >
+    >::type p;
+
+BOOST_MPL_ASSERT_RELATION( p::first::value, ==, 8 );
+BOOST_MPL_ASSERT_RELATION( p::second::value, ==, 3 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/partition.html b/doc/refmanual/partition.html new file mode 100644 index 0000000..ec19853 --- /dev/null +++ b/doc/refmanual/partition.html @@ -0,0 +1,136 @@ + + + + + + +The MPL Reference Manual: partition + + + + + +
Front Page / Algorithms / Transformation Algorithms / partition
+
+

partition

+
+

Synopsis

+
+template<
+      typename Seq
+    , typename Pred
+    , typename In1 = unspecified
+    , typename In2 = unspecified
+    >
+struct partition
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a pair of sequences together containing all elements in the range +[begin<Seq>::type, end<Seq>::type) split into two groups based on the predicate Pred. +partition is a synonym for stable_partition.

+

[Note: This wording applies to a no-inserter version(s) of the algorithm. See the +Expression semantics subsection for a precise specification of the algorithm's +details in all cases — end note]

+
+
+

Header

+
+#include <boost/mpl/partition.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SeqForward SequenceAn original sequence.
PredUnary Lambda ExpressionA partitioning predicate.
In1, In2InserterOutput inserters.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Reversible Algorithm.

+

For any Forward Sequence s, an unary Lambda Expression pred, and Inserters +in1 and in2:

+
+typedef partition<s,pred,in1,in2>::type r;
+
+ +++ + + + + + +
Return type:A pair.
Semantics:

Equivalent to

+
+typedef stable_partition<s,pred,in1,in2>::type r;
+
+
+
+
+

Complexity

+

Linear. Exactly size<s>::value applications of pred, and size<s>::value +of summarized in1::operation / in2::operation applications.

+
+
+

Example

+
+template< typename N > struct is_odd : bool_<(N::value % 2)> {};
+
+typedef partition<
+      range_c<int,0,10> 
+    , is_odd<_1>
+    , back_inserter< vector<> >
+    , back_inserter< vector<> >
+    >::type r;
+
+BOOST_MPL_ASSERT(( equal< r::first, vector_c<int,1,3,5,7,9> > ));
+BOOST_MPL_ASSERT(( equal< r::second, vector_c<int,0,2,4,6,8> > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/placeholder-expression.html b/doc/refmanual/placeholder-expression.html new file mode 100644 index 0000000..6103923 --- /dev/null +++ b/doc/refmanual/placeholder-expression.html @@ -0,0 +1,55 @@ + + + + + + +The MPL Reference Manual: Placeholder Expression + + + + + +
Front Page / Metafunctions / Concepts / Placeholder Expression
+
+

Placeholder Expression

+
+

Description

+

A Placeholder Expression is a type that is either a placeholder or a class +template specialization with at least one argument that itself is a +Placeholder Expression.

+
+
+

Expression requirements

+

If X is a class template, and a1,... an are arbitrary types, then +X<a1,...,an> is a Placeholder Expression if and only if all of the following +conditions hold:

+ +
+
+

Models

+ +
+ +
+ + + + + diff --git a/doc/refmanual/placeholders.html b/doc/refmanual/placeholders.html new file mode 100644 index 0000000..5f4292b --- /dev/null +++ b/doc/refmanual/placeholders.html @@ -0,0 +1,99 @@ + + + + + + +The MPL Reference Manual: Placeholders + + + + + +
Front Page / Metafunctions / Composition and Argument Binding / Placeholders
+
+

Placeholders

+
+

Synopsis

+
+namespace placeholders {
+typedef unspecified _;
+typedef arg<1>      _1;
+typedef arg<2>      _2;
+...
+typedef arg<n>      _n;
+}
+
+using placeholders::_;
+using placeholders::_1;
+using placeholders::_2;
+...
+using placeholders::_n;
+
+
+
+

Description

+

A placeholder in a form _n is simply a synonym for the corresponding +arg<n> specialization. The unnamed placeholder _ (underscore) carries +special meaning in bind and lambda expressions, and does not have +defined semantics outside of these contexts.

+

Placeholder names can be made available in the user namespace through +using namespace mpl::placeholders; directive.

+
+
+

Header

+
+#include <boost/mpl/placeholders.hpp>
+
+

[Note: The include might be omitted when using placeholders to construct a Lambda Expression for passing it to MPL's own algorithm or metafunction: any library +component that is documented to accept a lambda expression makes the placeholders +implicitly available for the user code — end note]

+
+
+

Parameters

+

None.

+
+
+

Expression semantics

+

For any integral constant n in the range [1, BOOST_MPL_LIMIT_METAFUNCTION_ARITY] and +arbitrary types a1,... an:

+
+typedef apply_wrapn<_n,a1,...an>::type x;
+
+ +++ + + + + + +
Return type:A type.
Semantics:

Equivalent to

+
+typedef apply_wrapn< arg<n>,a1,...an >::type x;
+
+
+
+
+

Example

+
+typedef apply_wrap5< _1,bool,char,short,int,long >::type t1;
+typedef apply_wrap5< _3,bool,char,short,int,long >::type t3;
+
+BOOST_MPL_ASSERT(( is_same< t1, bool > ));
+BOOST_MPL_ASSERT(( is_same< t3, short > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/plus.html b/doc/refmanual/plus.html new file mode 100644 index 0000000..1474023 --- /dev/null +++ b/doc/refmanual/plus.html @@ -0,0 +1,140 @@ + + + + + + +The MPL Reference Manual: plus + + + + + +
Front Page / Metafunctions / Arithmetic Operations / plus
+
+

plus

+
+

Synopsis

+
+template<
+      typename T1
+    , typename T2
+    , typename T3 = unspecified
+    ...
+    , typename Tn = unspecified
+    >
+struct plus
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the sum of its arguments.

+
+
+

Header

+
+#include <boost/mpl/plus.hpp>
+#include <boost/mpl/arithmetic.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
T1, T2,... TnIntegral ConstantOperation's arguments.
+

[Note: The requirements listed in this specification +are the ones imposed by the default implementation. See Numeric Metafunction concept +for the details on how to provide an implementation for a user-defined numeric type +that does not satisfy the Integral Constant requirements. — end note]

+
+
+

Expression semantics

+

For any Integral Constants c1,c2,... cn:

+
+typedef plus<c1,...cn>::type r; 
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+typedef integral_c<
+      typeof(c1::value + c2::value)
+    , ( c1::value + c2::value )
+    > c;
+    
+typedef plus<c,c3,...cn>::type r; 
+
+
+ +
+typedef plus<c1,...cn> r;
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+struct r : plus<c1,...cn>::type {};
+
+
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef plus< int_<-10>, int_<3>, long_<1> >::type r;
+BOOST_MPL_ASSERT_RELATION( r::value, ==, -6 );
+BOOST_MPL_ASSERT(( is_same< r::value_type, long > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/pop-back.html b/doc/refmanual/pop-back.html new file mode 100644 index 0000000..0c0f487 --- /dev/null +++ b/doc/refmanual/pop-back.html @@ -0,0 +1,120 @@ + + + + + + +The MPL Reference Manual: pop_back + + + + + +
Front Page / Sequences / Intrinsic Metafunctions / pop_back
+
+

pop_back

+
+

Synopsis

+
+template<
+      typename Sequence
+    >
+struct pop_back
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

pop_back performs a removal at the end of the sequence with guaranteed O(1) +complexity.

+
+
+

Header

+
+#include <boost/mpl/pop_back.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceBack Extensible SequenceA sequence to erase the last element from.
+
+
+

Expression semantics

+

For any Back Extensible Sequence s:

+
+typedef pop_back<s>::type r; 
+
+ +++ + + + + + + + + + +
Return type:Back Extensible Sequence.
Precondition:empty<s>::value == false.
Semantics:Equivalent to erase<s,end<s>::type>::type;.
Postcondition:size<r>::value == size<s>::value - 1.
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef vector<long>::type types1;
+typedef vector<long,int>::type types2;
+typedef vector<long,int,char>::type types3;
+
+typedef pop_back<types1>::type result1;
+typedef pop_back<types2>::type result2;
+typedef pop_back<types3>::type result3;
+    
+BOOST_MPL_ASSERT_RELATION( size<result1>::value, ==, 0 );
+BOOST_MPL_ASSERT_RELATION( size<result2>::value, ==, 1 );
+BOOST_MPL_ASSERT_RELATION( size<result3>::value, ==, 2 );
+    
+BOOST_MPL_ASSERT(( is_same< back<result2>::type, long> ));
+BOOST_MPL_ASSERT(( is_same< back<result3>::type, int > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/pop-front.html b/doc/refmanual/pop-front.html new file mode 100644 index 0000000..a78c117 --- /dev/null +++ b/doc/refmanual/pop-front.html @@ -0,0 +1,120 @@ + + + + + + +The MPL Reference Manual: pop_front + + + + + +
Front Page / Sequences / Intrinsic Metafunctions / pop_front
+
+

pop_front

+
+

Synopsis

+
+template<
+      typename Sequence
+    >
+struct pop_front
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

pop_front performs a removal at the beginning of the sequence with guaranteed O(1) +complexity.

+
+
+

Header

+
+#include <boost/mpl/pop_front.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceFront Extensible SequenceA sequence to erase the first element from.
+
+
+

Expression semantics

+

For any Front Extensible Sequence s:

+
+typedef pop_front<s>::type r; 
+
+ +++ + + + + + + + + + +
Return type:Front Extensible Sequence.
Precondition:empty<s>::value == false.
Semantics:Equivalent to erase<s,begin<s>::type>::type;.
Postcondition:size<r>::value == size<s>::value - 1.
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef vector<long>::type types1;
+typedef vector<int,long>::type types2;
+typedef vector<char,int,long>::type types3;
+
+typedef pop_front<types1>::type result1;
+typedef pop_front<types2>::type result2;
+typedef pop_front<types3>::type result3;
+    
+BOOST_MPL_ASSERT_RELATION( size<result1>::value, ==, 0 );
+BOOST_MPL_ASSERT_RELATION( size<result2>::value, ==, 1 );
+BOOST_MPL_ASSERT_RELATION( size<result3>::value, ==, 2 );
+    
+BOOST_MPL_ASSERT(( is_same< front<result2>::type, long > ));
+BOOST_MPL_ASSERT(( is_same< front<result3>::type, int > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/prior.html b/doc/refmanual/prior.html new file mode 100644 index 0000000..671e122 --- /dev/null +++ b/doc/refmanual/prior.html @@ -0,0 +1,115 @@ + + + + + + +The MPL Reference Manual: prior + + + + + +
Front Page / Iterators / Iterator Metafunctions / prior
+
+

prior

+
+

Synopsis

+
+template<
+      typename Iterator
+    >
+struct prior
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the previous iterator in the sequence. [Note: prior has a number of +overloaded meanings, depending on the type of its argument. For instance, +if X is an Integral Constant, prior<X> returns an decremented +Integral Constant of the same type. The following specification is +iterator-specific. Please refer to the corresponding concept's +documentation for the details of the alternative semantics — end note].

+
+
+

Header

+
+#include <boost/mpl/next_prior.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
IteratorForward Iterator.An iterator to decrement.
+
+
+

Expression semantics

+

For any Forward Iterators iter:

+
+typedef prior<iter>::type j; 
+
+ +++ + + + + + + + +
Return type:Forward Iterator.
Precondition:iter is decrementable.
Semantics:

j is an iterator pointing to the previous element in the sequence. +If iter is a user-defined iterator, the library-provided default +implementation is equivalent to

+
+typedef iter::prior j;
+
+
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef vector_c<int,1> v;
+typedef begin<v>::type first;
+typedef end<v>::type last;
+
+BOOST_MPL_ASSERT(( is_same< prior<last>::type, first > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/protect.html b/doc/refmanual/protect.html new file mode 100644 index 0000000..ed956a0 --- /dev/null +++ b/doc/refmanual/protect.html @@ -0,0 +1,127 @@ + + + + + + +The MPL Reference Manual: protect + + + + + +
Front Page / Metafunctions / Composition and Argument Binding / protect
+
+

protect

+
+

Synopsis

+
+template< 
+      typename F
+    >
+struct protect
+{
+    // unspecified
+    // ...
+};
+
+
+
+

Description

+

protect is an identity wrapper for a Metafunction Class that prevents +its argument from being recognized as a bind expression.

+
+
+

Header

+
+#include <boost/mpl/protect.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
FMetafunction ClassA metafunction class to wrap.
+
+
+

Expression semantics

+

For any Metafunction Class f:

+
+typedef protect<f> g;
+
+ +++ + + + + + +
Return type:Metafunction Class.
Semantics:

If f is a bind expression, equivalent to

+
+struct g
+{
+    template< 
+          typename U1 = unspecified,... typename Un = unspecified
+        >
+    struct apply
+        : apply_wrapn<f,U1,...Un>
+    {
+    };
+};
+
+

otherwise equivalent to typedef f g;.

+
+
+
+

Example

+
+FIXME
+
+struct f
+{
+    template< typename T1, typename T2 > struct apply
+    {
+        // ...
+    };
+};
+
+typedef bind<_1, protect< bind<f,_1,_2> > >
+
+typedef apply_wrap0< f0 >::type r1;
+typedef apply_wrap0< g0 >::type r2;
+typedef apply_wrap2< f2,int,char >::type r3;
+
+BOOST_MPL_ASSERT(( is_same<r1,char> ));
+BOOST_MPL_ASSERT(( is_same<r2,char> ));
+BOOST_MPL_ASSERT(( is_same<r3,char> ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/push-back.html b/doc/refmanual/push-back.html new file mode 100644 index 0000000..38467ee --- /dev/null +++ b/doc/refmanual/push-back.html @@ -0,0 +1,126 @@ + + + + + + +The MPL Reference Manual: push_back + + + + + +
Front Page / Sequences / Intrinsic Metafunctions / push_back
+
+

push_back

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename T
+    >
+struct push_back
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

push_back performs an insertion at the end of the sequence with guaranteed O(1) +complexity.

+
+
+

Header

+
+#include <boost/mpl/push_back.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceBack Extensible SequenceA sequence to insert into.
TAny typeThe element to be inserted.
+
+
+

Expression semantics

+

For any Back Extensible Sequence s and arbitrary type x:

+
+typedef push_back<s,x>::type r;
+
+ +++ + + + + + + + +
Return type:Back Extensible Sequence.
Semantics:

Equivalent to

+
+typedef insert< s,end<s>::type,x >::type r;
+
+
Postcondition:

back<r>::type is identical to x;

+
+size<r>::value == size<s>::value + 1
+
+
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef vector_c<bool,false,false,false,
+    true,true,true,false,false> bools;
+
+typedef push_back<bools,false_>::type message;
+
+BOOST_MPL_ASSERT_RELATION( back<message>::type::value, ==, false );
+BOOST_MPL_ASSERT_RELATION( 
+      ( count_if<message, equal_to<_1,false_> >::value ), ==, 6
+    );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/push-front.html b/doc/refmanual/push-front.html new file mode 100644 index 0000000..b1c6393 --- /dev/null +++ b/doc/refmanual/push-front.html @@ -0,0 +1,125 @@ + + + + + + +The MPL Reference Manual: push_front + + + + + +
Front Page / Sequences / Intrinsic Metafunctions / push_front
+
+

push_front

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename T
+    >
+struct push_front
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

push_front performs an insertion at the beginning of the sequence with guaranteed O(1) +complexity.

+
+
+

Header

+
+#include <boost/mpl/push_front.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceFront Extensible SequenceA sequence to insert into.
TAny typeThe element to be inserted.
+
+
+

Expression semantics

+

For any Front Extensible Sequence s and arbitrary type x:

+
+typedef push_front<s,x>::type r;
+
+ +++ + + + + + + + +
Return type:Front Extensible Sequence.
Semantics:

Equivalent to

+
+typedef insert< s,begin<s>::type,x >::type r;
+
+
Postcondition:size<r>::value == size<s>::value + 1; +front<r>::type is identical to x.
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef vector_c<int,1,2,3,5,8,13,21> v;
+BOOST_MPL_ASSERT_RELATION( size<v>::value, ==, 7 );
+
+typedef push_front< v,integral_c<int,1> >::type fibonacci;
+BOOST_MPL_ASSERT_RELATION( size<fibonacci>::value, ==, 8 );
+
+BOOST_MPL_ASSERT(( equal< 
+      fibonacci
+    , vector_c<int,1,1,2,3,5,8,13,21>
+    , equal_to<_,_>
+    > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/querying-algorithms.html b/doc/refmanual/querying-algorithms.html new file mode 100644 index 0000000..097218b --- /dev/null +++ b/doc/refmanual/querying-algorithms.html @@ -0,0 +1,35 @@ + + + + + + +The MPL Reference Manual: Querying Algorithms + + + + + +
Front Page / Algorithms / Querying Algorithms
+ + + + + + diff --git a/doc/refmanual/quote.html b/doc/refmanual/quote.html new file mode 100644 index 0000000..ee892c4 --- /dev/null +++ b/doc/refmanual/quote.html @@ -0,0 +1,156 @@ + + + + + + +The MPL Reference Manual: quote + + + + + +
Front Page / Metafunctions / Composition and Argument Binding / quote
+
+

quote

+
+

Synopsis

+
+template<
+      template< typename P1 > class F
+    , typename Tag = unspecified
+    >
+struct quote1
+{
+    // unspecified
+    // ...
+};    
+
+...
+
+template<
+      template< typename P1,... typename Pn > class F
+    , typename Tag = unspecified
+    >
+struct quoten
+{
+    // unspecified
+    // ...
+};    
+
+
+
+

Description

+

quoten is a higher-order primitive that wraps an n-ary Metafunction to create +a corresponding Metafunction Class.

+
+
+

Header

+
+#include <boost/mpl/quote.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
FMetafunctionA metafunction to wrap.
TagAny typeA tag determining wrap semantics.
+
+
+

Expression semantics

+

For any n-ary Metafunction f and arbitrary type tag:

+
+typedef quoten<f> g;
+typedef quoten<f,tag> g;
+
+ +++ + + + + + +
Return type:Metafunction Class
Semantics:

Equivalent to

+
+struct g
+{
+    template< typename A1,... typename An > struct apply
+        : f<A1,...An>
+    {
+    };
+};
+
+

if f<A1,...An> has a nested type member ::type, and to

+
+struct g
+{
+    template< typename A1,... typename An > struct apply
+    {
+        typedef f<A1,...An> type;
+    };
+};
+
+

otherwise.

+
+
+
+

Example

+
+template< typename T > struct f1
+{
+    typedef T type;
+};
+
+template<
+    typename T1, typename T2, typename T3, typename T4, typename T5
+    >
+struct f5
+{
+    // no 'type' member!
+};
+
+typedef quote1<f1>::apply<int>::type t1;
+typedef quote5<f5>::apply<char,short,int,long,float>::type t5;
+
+BOOST_MPL_ASSERT(( is_same< t1, int > ));
+BOOST_MPL_ASSERT(( is_same< t5, f5<char,short,int,long,float> > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/random-access-iterator.html b/doc/refmanual/random-access-iterator.html new file mode 100644 index 0000000..5c266ff --- /dev/null +++ b/doc/refmanual/random-access-iterator.html @@ -0,0 +1,113 @@ + + + + + + +The MPL Reference Manual: Random Access Iterator + + + + + +
Front Page / Iterators / Concepts / Random Access Iterator
+
+

Random Access Iterator

+
+

Description

+

A Random Access Iterator is a Bidirectional Iterator that provides +constant-time guarantees on moving the iterator an arbitrary number of positions +forward or backward and for measuring the distance to another iterator in the +same sequence.

+
+ +
+

Expression requirements

+

In addition to the requirements defined in Bidirectional Iterator, +the following requirements must be met.

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionTypeComplexity
next<i>::typeRandom Access IteratorAmortized constant time
prior<i>::typeRandom Access IteratorAmortized constant time
i::categoryIntegral Constant, convertible +to random_access_iterator_tagConstant time
advance<i,n>::typeRandom Access IteratorAmortized constant time
distance<i,j>::typeIntegral ConstantAmortized constant time
+
+
+

Expression semantics

+
+typedef advance<i,n>::type j;
+
+ +++ + + + +
Semantics:See advance specification
+ +
+typedef distance<i,j>::type n;
+
+ +++ + + + +
Semantics:See distance specification
+
+
+

Invariants

+

For any random access iterators i and j the following invariants always +hold:

+ +
+ +
+ + + + + diff --git a/doc/refmanual/random-access-sequence.html b/doc/refmanual/random-access-sequence.html new file mode 100644 index 0000000..53de1c6 --- /dev/null +++ b/doc/refmanual/random-access-sequence.html @@ -0,0 +1,98 @@ + + + + + + +The MPL Reference Manual: Random Access Sequence + + + + + +
Front Page / Sequences / Concepts / Random Access Sequence
+
+

Random Access Sequence

+
+

Description

+

A Random Access Sequence is a Bidirectional Sequence whose iterators model +Random Access Iterator. A random access sequence guarantees amortized constant +time access to an arbitrary sequence element.

+
+ +
+

Expression requirements

+

In addition to the requirements defined in Bidirectional Sequence, +for any Random Access Sequence s the following must be met:

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ExpressionTypeComplexity
begin<s>::typeRandom Access IteratorAmortized constant time
end<s>::typeRandom Access IteratorAmortized constant time
at<s,n>::typeAny typeAmortized constant time
+
+
+

Expression semantics

+

Semantics of an expression is defined only where it differs from, or is not +defined in Bidirectional Sequence.

+ ++++ + + + + + + + + + + +
ExpressionSemantics
at<s,n>::typeThe nth element from the beginning of the sequence; see at.
+
+ + +
+ + + + + diff --git a/doc/refmanual/range-c.html b/doc/refmanual/range-c.html new file mode 100644 index 0000000..e9566b1 --- /dev/null +++ b/doc/refmanual/range-c.html @@ -0,0 +1,144 @@ + + + + + + +The MPL Reference Manual: range_c + + + + + +
Front Page / Sequences / Classes / range_c
+
+

range_c

+
+

Synopsis

+
+template<
+      typename T
+    , T Start
+    , T Finish
+    >
+struct range_c
+{
+    typedef integral_c<T,Start> start;
+    typedef integral_c<T,Finish> finish;
+    // unspecified
+    // ...
+};
+
+
+
+

Description

+

range_c is a sorted Random Access Sequence of Integral Constants. Note +that because it is not an Extensible Sequence, sequence-building +intrinsic metafunctions such as push_front and transformation algorithms +such as replace are not directly applicable — to be able to use +them, you'd first need to copy the content of the range into a more suitable +sequence.

+
+
+

Header

+
+#include <boost/mpl/range_c.hpp>
+
+
+ +
+

Expression semantics

+

In the following table, r is an instance of range_c, n is an Integral Constant, +T is an arbitrary integral type, and n and m are integral constant values of type T.

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionSemantics
+range_c<T,n,m>
+range_c<T,n,m>::type
+
+
A sorted Random Access Sequence of integral constant +wrappers for the half-open range of values [n, +m): integral_c<T,n>, integral_c<T,n+1>,... +integral_c<T,m-1>.
begin<r>::typeAn iterator pointing to the beginning of r; +see Random Access Sequence.
end<r>::typeAn iterator pointing to the end of r; +see Random Access Sequence.
size<r>::typeThe size of r; see Random Access Sequence.
empty<r>::typeA boolean Integral Constant c such that +c::value == true if and only if r is empty; see +Random Access Sequence.
front<r>::typeThe first element in r; see +Random Access Sequence.
back<r>::typeThe last element in r; see +Random Access Sequence.
at<r,n>::typeThe nth element from the beginning of r; see +Random Access Sequence.
+
+
+

Example

+
+typedef range_c<int,0,0> range0;
+typedef range_c<int,0,1> range1;
+typedef range_c<int,0,10> range10;
+
+BOOST_MPL_ASSERT_RELATION( size<range0>::value, ==, 0 );
+BOOST_MPL_ASSERT_RELATION( size<range1>::value, ==, 1 );
+BOOST_MPL_ASSERT_RELATION( size<range10>::value, ==, 10 );
+
+BOOST_MPL_ASSERT(( empty<range0> ));
+BOOST_MPL_ASSERT_NOT(( empty<range1> ));
+BOOST_MPL_ASSERT_NOT(( empty<range10> ));
+
+BOOST_MPL_ASSERT(( is_same< begin<range0>::type, end<range0>::type > ));
+BOOST_MPL_ASSERT_NOT(( is_same< begin<range1>::type, end<range1>::type > ));
+BOOST_MPL_ASSERT_NOT(( is_same< begin<range10>::type, end<range10>::type > ));
+
+BOOST_MPL_ASSERT_RELATION( front<range1>::type::value, ==, 0 );
+BOOST_MPL_ASSERT_RELATION( back<range1>::type::value, ==, 0 );
+BOOST_MPL_ASSERT_RELATION( front<range10>::type::value, ==, 0 );
+BOOST_MPL_ASSERT_RELATION( back<range10>::type::value, ==, 9 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/refmanual_toc.html b/doc/refmanual/refmanual_toc.html new file mode 100644 index 0000000..52dc0fc --- /dev/null +++ b/doc/refmanual/refmanual_toc.html @@ -0,0 +1,302 @@ + + + + + + +The MPL Reference Manual: Full TOC + + + + +
+

Table of Contents

+ + + + + + diff --git a/doc/refmanual/remove-if.html b/doc/refmanual/remove-if.html new file mode 100644 index 0000000..2629b28 --- /dev/null +++ b/doc/refmanual/remove-if.html @@ -0,0 +1,140 @@ + + + + + + +The MPL Reference Manual: remove_if + + + + + +
Front Page / Algorithms / Transformation Algorithms / remove_if
+
+

remove_if

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename Pred
+    , typename In = unspecified
+    >
+struct remove_if
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a new sequence that contains all the elements from [begin<Sequence>::type, end<Sequence>::type) range +except those that satisfy the predicate Pred.

+ +

[Note: This wording applies to a no-inserter version(s) of the algorithm. See the +Expression semantics subsection for a precise specification of the algorithm's +details in all cases — end note]

+
+
+

Header

+
+#include <boost/mpl/remove_if.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceAn original sequence.
PredUnary Lambda ExpressionA removal condition.
InInserterAn inserter.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Reversible Algorithm.

+

For any Forward Sequence s, and an Inserter in, and an unary +Lambda Expression pred:

+
+typedef remove_if<s,pred,in>::type r; 
+
+ +++ + + + + + +
Return type:A type.
Semantics:

Equivalent to

+
+typedef lambda<pred>::type p;
+typedef lambda<in::operation>::type op;
+
+typedef fold<
+      s
+    , in::state
+    , eval_if<
+          apply_wrap1<p,_2>
+        , identity<_1>
+        , apply_wrap2<op,_1,_2>
+        >
+    >::type r;
+
+
+
+
+

Complexity

+

Linear. Performs exactly size<s>::value applications of pred, and at +most size<s>::value insertions.

+
+
+

Example

+
+typedef vector_c<int,1,4,5,2,7,5,3,5>::type numbers;
+typedef remove_if< numbers, greater<_,int_<4> > >::type result;
+
+BOOST_MPL_ASSERT(( equal< result,vector_c<int,1,4,2,3>,equal_to<_,_> > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/remove.html b/doc/refmanual/remove.html new file mode 100644 index 0000000..9f66f47 --- /dev/null +++ b/doc/refmanual/remove.html @@ -0,0 +1,128 @@ + + + + + + +The MPL Reference Manual: remove + + + + + +
Front Page / Algorithms / Transformation Algorithms / remove
+
+

remove

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename T
+    , typename In = unspecified
+    >
+struct remove
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a new sequence that contains all elements from [begin<Sequence>::type, end<Sequence>::type) +range except those that are identical to T.

+ +

[Note: This wording applies to a no-inserter version(s) of the algorithm. See the +Expression semantics subsection for a precise specification of the algorithm's +details in all cases — end note]

+
+
+

Header

+
+#include <boost/mpl/remove.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceAn original sequence.
TAny typeA type to be removed.
InInserterAn inserter.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Reversible Algorithm.

+

For any Forward Sequence s, an Inserter in, and arbitrary type x:

+
+typedef remove<s,x,in>::type r; 
+
+ +++ + + + + + +
Return type:A type.
Semantics:

Equivalent to

+
+typedef remove_if< s,is_same<_,x>,in >::type r;
+
+
+
+
+

Complexity

+

Linear. Performs exactly size<s>::value comparisons for equality, and at +most size<s>::value insertions.

+
+
+

Example

+
+typedef vector<int,float,char,float,float,double>::type types;
+typedef remove< types,float >::type result;
+
+BOOST_MPL_ASSERT(( equal< result, vector<int,char,double> > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/replace-if.html b/doc/refmanual/replace-if.html new file mode 100644 index 0000000..f471f37 --- /dev/null +++ b/doc/refmanual/replace-if.html @@ -0,0 +1,133 @@ + + + + + + +The MPL Reference Manual: replace_if + + + + + +
Front Page / Algorithms / Transformation Algorithms / replace_if
+
+

replace_if

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename Pred
+    , typename In = unspecified
+    >
+struct replace_if
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a copy of the original sequence where every type that satisfies +the predicate Pred has been replaced with NewType.

+

[Note: This wording applies to a no-inserter version(s) of the algorithm. See the +Expression semantics subsection for a precise specification of the algorithm's +details in all cases — end note]

+
+
+

Header

+
+#include <boost/mpl/replace_if.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceAn original sequence.
PredUnary Lambda ExpressionA replacement condition.
NewTypeAny typeA type to replace with.
InInserterAn inserter.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Reversible Algorithm.

+

For any Forward Sequence s, an unary Lambda Expression pred, +an Inserter in, and arbitrary type x:

+
+typedef replace_if<s,pred,x,in>::type r; 
+
+ +++ + + + + + +
Return type:A type.
Semantics:

Equivalent to

+
+typedef lambda<pred>::type p;
+typedef transform< s, if_< apply_wrap1<p,_1>,x,_1>, in >::type r; 
+
+
+
+
+

Complexity

+

Linear. Performs exactly size<s>::value applications of pred, and at most +size<s>::value insertions.

+
+
+

Example

+
+typedef vector_c<int,1,4,5,2,7,5,3,5> numbers;
+typedef vector_c<int,1,4,0,2,0,0,3,0> expected;
+typedef replace_if< numbers, greater<_,int_<4> >, int_<0> >::type result;
+
+BOOST_MPL_ASSERT(( equal< result,expected, equal_to<_,_> > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/replace.html b/doc/refmanual/replace.html new file mode 100644 index 0000000..fce9a3e --- /dev/null +++ b/doc/refmanual/replace.html @@ -0,0 +1,132 @@ + + + + + + +The MPL Reference Manual: replace + + + + + +
Front Page / Algorithms / Transformation Algorithms / replace
+
+

replace

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename OldType
+    , typename NewType
+    , typename In = unspecified
+    >
+struct replace
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a copy of the original sequence where every type identical to OldType +has been replaced with NewType.

+

[Note: This wording applies to a no-inserter version(s) of the algorithm. See the +Expression semantics subsection for a precise specification of the algorithm's +details in all cases — end note]

+
+
+

Header

+
+#include <boost/mpl/replace.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceA original sequence.
OldTypeAny typeA type to be replaced.
NewTypeAny typeA type to replace with.
InInserterAn inserter.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Reversible Algorithm.

+

For any Forward Sequence s, an Inserter in, and arbitrary types x and y:

+
+typedef replace<s,x,y,in>::type r; 
+
+ +++ + + + + + +
Return type:A type.
Semantics:

Equivalent to

+
+typedef replace_if< s,y,is_same<_,x>,in >::type r; 
+
+
+
+
+

Complexity

+

Linear. Performs exactly size<s>::value comparisons for +identity / insertions.

+
+
+

Example

+
+typedef vector<int,float,char,float,float,double> types;
+typedef vector<int,double,char,double,double,double> expected;
+typedef replace< types,float,double >::type result;
+
+BOOST_MPL_ASSERT(( equal< result,expected > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/reverse-copy-if.html b/doc/refmanual/reverse-copy-if.html new file mode 100644 index 0000000..1edcdc2 --- /dev/null +++ b/doc/refmanual/reverse-copy-if.html @@ -0,0 +1,142 @@ + + + + + + +The MPL Reference Manual: reverse_copy_if + + + + + +
Front Page / Algorithms / Transformation Algorithms / reverse_copy_if
+
+

reverse_copy_if

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename Pred
+    , typename In = unspecified
+    >
+struct reverse_copy_if
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a reversed, filtered copy of the original sequence containing the +elements that satisfy the predicate Pred.

+

[Note: This wording applies to a no-inserter version(s) of the algorithm. See the +Expression semantics subsection for a precise specification of the algorithm's +details in all cases — end note]

+
+
+

Header

+
+#include <boost/mpl/copy_if.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceA sequence to copy.
PredUnary Lambda ExpressionA copying condition.
InInserterAn inserter.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Reversible Algorithm.

+

For any Forward Sequence s, an unary Lambda Expression pred, and +an Inserter in:

+
+typedef reverse_copy_if<s,pred,in>::type r; 
+
+ +++ + + + + + +
Return type:A type
Semantics:

Equivalent to

+
+typedef lambda<pred>::type p;
+typedef lambda<in::operation>::type op;
+
+typedef reverse_fold<
+      s
+    , in::state
+    , eval_if<
+          apply_wrap1<p,_2>
+        , apply_wrap2<op,_1,_2>
+        , identity<_1>
+        >
+    >::type r;
+
+
+
+
+

Complexity

+

Linear. Exactly size<s>::value applications of pred, and at +most size<s>::value applications of in::operation.

+
+
+

Example

+
+typedef reverse_copy_if<
+      range_c<int,0,10>
+    , less< _1, int_<5> >
+    , front_inserter< vector<> >
+    >::type result;
+
+BOOST_MPL_ASSERT_RELATION( size<result>::value, ==, 5 );
+BOOST_MPL_ASSERT(( equal<result,range_c<int,0,5> > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/reverse-copy.html b/doc/refmanual/reverse-copy.html new file mode 100644 index 0000000..a75418c --- /dev/null +++ b/doc/refmanual/reverse-copy.html @@ -0,0 +1,123 @@ + + + + + + +The MPL Reference Manual: reverse_copy + + + + + +
Front Page / Algorithms / Transformation Algorithms / reverse_copy
+
+

reverse_copy

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename In = unspecified
+    >
+struct reverse_copy
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a reversed copy of the original sequence.

+

[Note: This wording applies to a no-inserter version(s) of the algorithm. See the +Expression semantics subsection for a precise specification of the algorithm's +details in all cases — end note]

+
+
+

Header

+
+#include <boost/mpl/copy.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceA sequence to copy.
InInserterAn inserter.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Reversible Algorithm.

+

For any Forward Sequence s, and an Inserter in:

+
+typedef reverse_copy<s,in>::type r; 
+
+ +++ + + + + + +
Return type:A type.
Semantics:

Equivalent to

+
+typedef reverse_fold< s,in::state,in::operation >::type r; 
+
+
+
+
+

Complexity

+

Linear. Exactly size<s>::value applications of in::operation.

+
+
+

Example

+
+typedef list_c<int,10,11,12,13,14,15,16,17,18,19>::type numbers;
+typedef reverse_copy<
+      range_c<int,0,10>
+    , front_inserter< numbers >
+    >::type result;
+
+BOOST_MPL_ASSERT_RELATION( size<result>::value, ==, 20 );
+BOOST_MPL_ASSERT(( equal< result,range_c<int,0,20> > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/reverse-fold.html b/doc/refmanual/reverse-fold.html new file mode 100644 index 0000000..5fbe126 --- /dev/null +++ b/doc/refmanual/reverse-fold.html @@ -0,0 +1,169 @@ + + + + + + +The MPL Reference Manual: reverse_fold + + + + + +
Front Page / Algorithms / Iteration Algorithms / reverse_fold
+
+

reverse_fold

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename State
+    , typename BackwardOp
+    , typename ForwardOp = _1
+    >
+struct reverse_fold
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the result of the successive application of binary BackwardOp to the +result of the previous BackwardOp invocation (State if it's the first call) +and every element in the range [begin<Sequence>::type, end<Sequence>::type) in +reverse order. If ForwardOp is provided, then it is applied on forward +traversal to form the result that is passed to the first BackwardOp call.

+
+ + +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceA sequence to iterate.
StateAny typeThe initial state for the first BackwardOp +/ ForwardOp application.
BackwardOpBinary Lambda ExpressionThe operation to be executed on backward +traversal.
ForwardOpBinary Lambda ExpressionThe operation to be executed on forward +traversal.
+
+
+

Expression semantics

+

For any Forward Sequence s, binary Lambda Expression backward_op and forward_op, +and arbitrary type state:

+
+typedef reverse_fold< s,state,backward_op >::type t; 
+
+ +++ + + + + + +
Return type:A type
Semantics:

Equivalent to

+
+typedef reverse_iter_fold< 
+      s
+    , state
+    , apply<backward_op,_1,deref<_2> >
+    >::type t; 
+
+
+ +
+typedef reverse_fold< s,state,backward_op,forward_op >::type t; 
+
+ +++ + + + + + +
Return type:A type.
Semantics:

Equivalent to

+
+typedef reverse_fold<
+      Sequence
+    , fold<s,state,forward_op>::type
+    , backward_op
+    >::type t;        
+
+
+
+
+

Complexity

+

Linear. Exactly size<s>::value applications of backward_op and forward_op.

+
+
+

Example

+

Remove negative elements from a sequence [2].

+
+typedef list_c<int,5,-1,0,-7,-2,0,-5,4> numbers;
+typedef list_c<int,-1,-7,-2,-5> negatives;
+typedef reverse_fold<
+      numbers
+    , list_c<int>
+    , if_< less< _2,int_<0> >, push_front<_1,_2,>, _1 >
+    >::type result;
+
+BOOST_MPL_ASSERT(( equal< negatives,result > ));
+
+ + + + + +
[2]See remove_if for a more compact way to do this.
+
+ +
+ + + + + diff --git a/doc/refmanual/reverse-iter-fold.html b/doc/refmanual/reverse-iter-fold.html new file mode 100644 index 0000000..9192963 --- /dev/null +++ b/doc/refmanual/reverse-iter-fold.html @@ -0,0 +1,169 @@ + + + + + + +The MPL Reference Manual: reverse_iter_fold + + + + + +
Front Page / Algorithms / Iteration Algorithms / reverse_iter_fold
+
+

reverse_iter_fold

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename State
+    , typename BackwardOp
+    , typename ForwardOp = _1
+    >
+struct reverse_iter_fold
+{
+    typedef unspecified  type;
+};
+
+
+
+

Description

+

Returns the result of the successive application of binary BackwardOp to the +result of the previous BackwardOp invocation (State if it's the first call) +and each iterator in the range [begin<Sequence>::type, end<Sequence>::type) +in reverse order. If ForwardOp is provided, then it's applied on forward +traversal to form the result which is passed to the first BackwardOp call.

+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceA sequence to iterate.
StateAny typeThe initial state for the first BackwardOp +/ ForwardOp application.
BackwardOpBinary Lambda ExpressionThe operation to be executed on backward +traversal.
ForwardOpBinary Lambda ExpressionThe operation to be executed on forward +traversal.
+
+
+

Expression semantics

+

For any Forward Sequence s, binary Lambda Expression backward_op and forward_op, +and arbitrary type state:

+
+typedef reverse_iter_fold< s,state,backward_op >::type t; 
+
+ +++ + + + + + +
Return type:A type.
Semantics:

Equivalent to

+
+typedef begin<s>::type i1;
+typedef next<i1>::type i2;
+...
+typedef next<in>::type last;
+typedef apply<backward_op,state,in>::type staten;
+typedef apply<backward_op,staten,in-1>::type staten-1; 
+...
+typedef apply<backward_op,state2,i1>::type state1; 
+typedef state1 t;
+
+

where n == size<s>::value and last is identical to end<s>::type; equivalent +to typedef state t; if empty<s>::value == true.

+
+ +
+typedef reverse_iter_fold< s,state,backward_op,forward_op >::type t; 
+
+ +++ + + + + + +
Return type:A type.
Semantics:

Equivalent to

+
+typedef reverse_iter_fold<
+      Sequence
+    , iter_fold<s,state,forward_op>::type
+    , backward_op
+    >::type t; 
+
+
+
+
+

Complexity

+

Linear. Exactly size<s>::value applications of backward_op and forward_op.

+
+
+

Example

+

Build a list of iterators to the negative elements in a sequence.

+
+typedef vector_c<int,5,-1,0,-7,-2,0,-5,4> numbers;
+typedef list_c<int,-1,-7,-2,-5> negatives;
+typedef reverse_iter_fold<
+      numbers
+    , list<>
+    , if_< less< deref<_2>,int_<0> >, push_front<_1,_2>, _1 >
+    >::type iters;
+
+BOOST_MPL_ASSERT(( equal< 
+      negatives
+    , transform_view< iters,deref<_1> >
+    > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/reverse-partition.html b/doc/refmanual/reverse-partition.html new file mode 100644 index 0000000..5946e63 --- /dev/null +++ b/doc/refmanual/reverse-partition.html @@ -0,0 +1,136 @@ + + + + + + +The MPL Reference Manual: reverse_partition + + + + + +
Front Page / Algorithms / Transformation Algorithms / reverse_partition
+
+

reverse_partition

+
+

Synopsis

+
+template<
+      typename Seq
+    , typename Pred
+    , typename In1 = unspecified
+    , typename In2 = unspecified
+    >
+struct reverse_partition
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a pair of sequences together containing all elements in the range +[begin<Seq>::type, end<Seq>::type) split into two groups based on the predicate Pred. +reverse_partition is a synonym for reverse_stable_partition.

+

[Note: This wording applies to a no-inserter version(s) of the algorithm. See the +Expression semantics subsection for a precise specification of the algorithm's +details in all cases — end note]

+
+
+

Header

+
+#include <boost/mpl/partition.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SeqForward SequenceAn original sequence.
PredUnary Lambda ExpressionA partitioning predicate.
In1, In2InserterOutput inserters.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Reversible Algorithm.

+

For any Forward Sequence s, an unary Lambda Expression pred, and Inserters +in1 and in2:

+
+typedef reverse_partition<s,pred,in1,in2>::type r;
+
+ +++ + + + + + +
Return type:A pair.
Semantics:

Equivalent to

+
+typedef reverse_stable_partition<s,pred,in1,in2>::type r;
+
+
+
+
+

Complexity

+

Linear. Exactly size<s>::value applications of pred, and size<s>::value +of summarized in1::operation / in2::operation applications.

+
+
+

Example

+
+template< typename N > struct is_odd : bool_<(N::value % 2)> {};
+
+typedef partition<
+      range_c<int,0,10> 
+    , is_odd<_1>
+    , back_inserter< vector<> >
+    , back_inserter< vector<> >
+    >::type r;
+
+BOOST_MPL_ASSERT(( equal< r::first, vector_c<int,9,7,5,3,1> > ));
+BOOST_MPL_ASSERT(( equal< r::second, vector_c<int,8,6,4,2,0> > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/reverse-remove-if.html b/doc/refmanual/reverse-remove-if.html new file mode 100644 index 0000000..27e4dd3 --- /dev/null +++ b/doc/refmanual/reverse-remove-if.html @@ -0,0 +1,139 @@ + + + + + + +The MPL Reference Manual: reverse_remove_if + + + + + +
Front Page / Algorithms / Transformation Algorithms / reverse_remove_if
+
+

reverse_remove_if

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename Pred
+    , typename In = unspecified
+    >
+struct reverse_remove_if
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a new sequence that contains all the elements from [begin<Sequence>::type, end<Sequence>::type) range +in reverse order except those that satisfy the predicate Pred.

+

[Note: This wording applies to a no-inserter version(s) of the algorithm. See the +Expression semantics subsection for a precise specification of the algorithm's +details in all cases — end note]

+
+
+

Header

+
+#include <boost/mpl/remove_if.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceAn original sequence.
PredUnary Lambda ExpressionA removal condition.
InInserterAn inserter.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Reversible Algorithm.

+

For any Forward Sequence s, and an Inserter in, and an unary +Lambda Expression pred:

+
+typedef reverse_remove_if<s,pred,in>::type r; 
+
+ +++ + + + + + +
Return type:A type.
Semantics:

Equivalent to

+
+typedef lambda<pred>::type p;
+typedef lambda<in::operation>::type op;
+
+typedef reverse_fold<
+      s
+    , in::state
+    , eval_if<
+          apply_wrap1<p,_2>
+        , identity<_1>
+        , apply_wrap2<op,_1,_2>
+        >
+    >::type r;
+
+
+
+
+

Complexity

+

Linear. Performs exactly size<s>::value applications of pred, and at +most size<s>::value insertions.

+
+
+

Example

+
+typedef vector_c<int,1,4,5,2,7,5,3,5>::type numbers;
+typedef reverse_remove_if< numbers, greater<_,int_<4> > >::type result;
+
+BOOST_MPL_ASSERT(( equal< result,vector_c<int,3,2,4,1>,equal_to<_,_> > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/reverse-remove.html b/doc/refmanual/reverse-remove.html new file mode 100644 index 0000000..56c5f90 --- /dev/null +++ b/doc/refmanual/reverse-remove.html @@ -0,0 +1,127 @@ + + + + + + +The MPL Reference Manual: reverse_remove + + + + + +
Front Page / Algorithms / Transformation Algorithms / reverse_remove
+
+

reverse_remove

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename T
+    , typename In = unspecified
+    >
+struct reverse_remove
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a new sequence that contains all elements from [begin<Sequence>::type, end<Sequence>::type) +range in reverse order except those that are identical to T.

+

[Note: This wording applies to a no-inserter version(s) of the algorithm. See the +Expression semantics subsection for a precise specification of the algorithm's +details in all cases — end note]

+
+
+

Header

+
+#include <boost/mpl/remove.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceAn original sequence.
TAny typeA type to be removed.
InInserterAn inserter.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Reversible Algorithm.

+

For any Forward Sequence s, an Inserter in, and arbitrary type x:

+
+typedef reverse_remove<s,x,in>::type r; 
+
+ +++ + + + + + +
Return type:A type.
Semantics:

Equivalent to

+
+typedef reverse_remove_if< s,is_same<_,x>,in >::type r;
+
+
+
+
+

Complexity

+

Linear. Performs exactly size<s>::value comparisons for equality, and at +most size<s>::value insertions.

+
+
+

Example

+
+typedef vector<int,float,char,float,float,double>::type types;
+typedef reverse_remove< types,float >::type result;
+
+BOOST_MPL_ASSERT(( equal< result, vector<double,char,int> > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/reverse-replace-if.html b/doc/refmanual/reverse-replace-if.html new file mode 100644 index 0000000..85068d3 --- /dev/null +++ b/doc/refmanual/reverse-replace-if.html @@ -0,0 +1,138 @@ + + + + + + +The MPL Reference Manual: reverse_replace_if + + + + + +
Front Page / Algorithms / Transformation Algorithms / reverse_replace_if
+
+

reverse_replace_if

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename Pred
+    , typename In = unspecified
+    >
+struct reverse_replace_if
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a reversed copy of the original sequence where every type that satisfies +the predicate Pred has been replaced with NewType.

+

[Note: This wording applies to a no-inserter version(s) of the algorithm. See the +Expression semantics subsection for a precise specification of the algorithm's +details in all cases — end note]

+
+
+

Header

+
+#include <boost/mpl/replace_if.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceAn original sequence.
PredUnary Lambda ExpressionA replacement condition.
NewTypeAny typeA type to replace with.
InInserterAn inserter.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Reversible Algorithm.

+

For any Forward Sequence s, an unary Lambda Expression pred, +an Inserter in, and arbitrary type x:

+
+typedef reverse_replace_if<s,pred,x,in>::type r; 
+
+ +++ + + + + + +
Return type:A type.
Semantics:

Equivalent to

+
+typedef lambda<pred>::type p;
+typedef reverse_transform< s, if_< apply_wrap1<p,_1>,x,_1>, in >::type r; 
+
+
+
+
+

Complexity

+

Linear. Performs exactly size<s>::value applications of pred, and at most +size<s>::value insertions.

+
+
+

Example

+
+typedef vector_c<int,1,4,5,2,7,5,3,5> numbers;
+typedef vector_c<int,1,4,0,2,0,0,3,0> expected;
+typedef reverse_replace_if< 
+      numbers
+    , greater< _, int_<4> >
+    , int_<0>
+    , front_inserter< vector<> >
+    >::type result;
+
+BOOST_MPL_ASSERT(( equal< result,expected, equal_to<_,_> > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/reverse-replace.html b/doc/refmanual/reverse-replace.html new file mode 100644 index 0000000..f82f8e1 --- /dev/null +++ b/doc/refmanual/reverse-replace.html @@ -0,0 +1,132 @@ + + + + + + +The MPL Reference Manual: reverse_replace + + + + + +
Front Page / Algorithms / Transformation Algorithms / reverse_replace
+
+

reverse_replace

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename OldType
+    , typename NewType
+    , typename In = unspecified
+    >
+struct reverse_replace
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a reversed copy of the original sequence where every type identical to OldType +has been replaced with NewType.

+

[Note: This wording applies to a no-inserter version(s) of the algorithm. See the +Expression semantics subsection for a precise specification of the algorithm's +details in all cases — end note]

+
+
+

Header

+
+#include <boost/mpl/replace.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceA original sequence.
OldTypeAny typeA type to be replaced.
NewTypeAny typeA type to replace with.
InInserterAn inserter.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Reversible Algorithm.

+

For any Forward Sequence s, an Inserter in, and arbitrary types x and y:

+
+typedef reverse_replace<s,x,y,in>::type r; 
+
+ +++ + + + + + +
Return type:A type.
Semantics:

Equivalent to

+
+typedef reverse_replace_if< s,y,is_same<_,x>,in >::type r; 
+
+
+
+
+

Complexity

+

Linear. Performs exactly size<s>::value comparisons for +identity / insertions.

+
+
+

Example

+
+typedef vector<int,float,char,float,float,double> types;
+typedef vector<double,double,double,char,double,int> expected;
+typedef reverse_replace< types,float,double >::type result;
+
+BOOST_MPL_ASSERT(( equal< result,expected > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/reverse-stable-partition.html b/doc/refmanual/reverse-stable-partition.html new file mode 100644 index 0000000..bd2e8ff --- /dev/null +++ b/doc/refmanual/reverse-stable-partition.html @@ -0,0 +1,148 @@ + + + + + + +The MPL Reference Manual: reverse_stable_partition + + + + + +
Front Page / Algorithms / Transformation Algorithms / reverse_stable_partition
+
+

reverse_stable_partition

+
+

Synopsis

+
+template<
+      typename Seq
+    , typename Pred
+    , typename In1 = unspecified
+    , typename In2 = unspecified
+    >
+struct reverse_stable_partition
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a pair of sequences together containing all elements in the range +[begin<Seq>::type, end<Seq>::type) split into two groups based on the predicate Pred. +reverse_stable_partition is guaranteed to preserve the reversed +relative order of the elements in the resulting sequences.

+

[Note: This wording applies to a no-inserter version(s) of the algorithm. See the +Expression semantics subsection for a precise specification of the algorithm's +details in all cases — end note]

+
+ + +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SeqForward SequenceAn original sequence.
PredUnary Lambda ExpressionA partitioning predicate.
In1, In2InserterOutput inserters.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Reversible Algorithm.

+

For any Forward Sequence s, an unary Lambda Expression pred, and Inserters +in1 and in2:

+
+typedef reverse_stable_partition<s,pred,in1,in2>::type r;
+
+ +++ + + + + + +
Return type:A pair.
Semantics:

Equivalent to

+
+typedef lambda<pred>::type p;
+typedef lambda<in1::operation>::type in1_op;
+typedef lambda<in2::operation>::type in2_op;
+
+typedef reverse_fold<
+      s
+    , pair< in1::state, in2::state >
+    , if_< 
+          apply_wrap1<p,_2>
+        , pair< apply_wrap2<in1_op,first<_1>,_2>, second<_1> >
+        , pair< first<_1>, apply_wrap2<in2_op,second<_1>,_2> >
+        >
+    >::type r;
+
+
+
+
+

Complexity

+

Linear. Exactly size<s>::value applications of pred, and size<s>::value +of summarized in1::operation / in2::operation applications.

+
+
+

Example

+
+template< typename N > struct is_odd : bool_<(N::value % 2)> {};
+
+typedef reverse_stable_partition<
+      range_c<int,0,10> 
+    , is_odd<_1>
+    , back_inserter< vector<> >
+    , back_inserter< vector<> >
+    >::type r;
+
+BOOST_MPL_ASSERT(( equal< r::first, vector_c<int,9,7,5,3,1> > ));
+BOOST_MPL_ASSERT(( equal< r::second, vector_c<int,8,6,4,2,0> > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/reverse-transform.html b/doc/refmanual/reverse-transform.html new file mode 100644 index 0000000..1f1362e --- /dev/null +++ b/doc/refmanual/reverse-transform.html @@ -0,0 +1,184 @@ + + + + + + +The MPL Reference Manual: reverse_transform + + + + + +
Front Page / Algorithms / Transformation Algorithms / reverse_transform
+
+

reverse_transform

+
+

Synopsis

+
+template<
+      typename Seq
+    , typename Op
+    , typename In = unspecified
+    >
+struct reverse_transform
+{
+    typedef unspecified type;
+};
+
+template<
+      typename Seq1
+    , typename Seq2
+    , typename BinaryOp
+    , typename In = unspecified
+    >
+struct reverse_transform
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

reverse_transform is an overloaded name:

+
    +
  • reverse_transform<Seq,Op> returns a reversed, transformed copy of the +original sequence produced by applying an unary transformation Op to +every element in the [begin<Sequence>::type, end<Sequence>::type) range.
  • +
  • reverse_transform<Seq1,Seq2,Op> returns a new sequence produced by applying a +binary transformation BinaryOp to a pair of elements (e1, e21) +from the corresponding [begin<Seq1>::type, end<Seq1>::type) and [begin<Seq2>::type, end<Seq2>::type) ranges in reverse +order.
  • +
+

[Note: This wording applies to a no-inserter version(s) of the algorithm. See the +Expression semantics subsection for a precise specification of the algorithm's +details in all cases — end note]

+
+
+

Header

+
+#include <boost/mpl/transform.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
Sequence, +Seq1, Seq2Forward SequenceSequences to transform.
Op, +BinaryOpLambda ExpressionA transformation.
InInserterAn inserter.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Reversible Algorithm.

+

For any Forward Sequences s, s1 and s2, Lambda Expressions op and op2, +and an Inserter in:

+
+typedef reverse_transform<s,op,in>::type r; 
+
+ +++ + + + + + +
Return type:A type.
Postcondition:

Equivalent to

+
+typedef lambda<op>::type f;
+typedef lambda<in::operation>::type in_op;
+
+typedef reverse_fold< 
+      s
+    , in::state
+    , bind< in_op, _1, bind<f, _2> > 
+    >::type r;
+
+
+
+typedef transform<s1,s2,op,in>::type r; 
+
+ +++ + + + + + +
Return type:A type.
Postcondition:

Equivalent to

+
+typedef lambda<op2>::type f;
+typedef lambda<in::operation>::type in_op;
+
+typedef reverse_fold< 
+      pair_view<s1,s2>
+    , in::state
+    , bind< 
+          in_op
+        , _1
+        , bind<f, bind<first<>,_2>, bind<second<>,_2> >
+        > 
+    >::type r;
+
+
+
+
+

Complexity

+

Linear. Exactly size<s>::value / size<s1>::value applications of +op / op2 and in::operation.

+
+
+

Example

+
+typedef vector<char,short,int,long,float,double> types;
+typedef vector<double*,float*,long*,int*,short*,char*> pointers;
+typedef reverse_transform< types,boost::add_pointer<_1> >::type result;
+
+BOOST_MPL_ASSERT(( equal<result,pointers> ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/reverse-unique.html b/doc/refmanual/reverse-unique.html new file mode 100644 index 0000000..3f8a68a --- /dev/null +++ b/doc/refmanual/reverse-unique.html @@ -0,0 +1,149 @@ + + + + + + +The MPL Reference Manual: reverse_unique + + + + + +
Front Page / Algorithms / Transformation Algorithms / reverse_unique
+
+

reverse_unique

+
+

Synopsis

+
+template<
+      typename Seq
+    , typename Pred
+    , typename In = unspecified
+    >
+struct reverse_unique
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a sequence of the initial elements of every subrange of the +reversed original sequence Seq whose elements are all the same.

+

[Note: This wording applies to a no-inserter version(s) of the algorithm. See the +Expression semantics subsection for a precise specification of the algorithm's +details in all cases — end note]

+
+
+

Header

+
+#include <boost/mpl/unique.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceAn original sequence.
PredBinary Lambda ExpressionAn equivalence relation.
InInserterAn inserter.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Reversible Algorithm.

+

For any Forward Sequence s, a binary Lambda Expression pred, +and an Inserter in:

+
+typedef reverse_unique<s,pred,in>::type r; 
+
+ +++ + + + + + +
Return type:A type.
Semantics:

If size<s>::value <= 1, then equivalent to

+
+typedef reverse_copy<s,in>::type r;
+
+

otherwise equivalent to

+
+typedef lambda<pred>::type p;
+typedef lambda<in::operation>::type in_op;
+typedef apply_wrap2<
+      in_op
+    , in::state
+    , front<types>::type 
+    >::type in_state;
+
+typedef reverse_fold<
+      s
+    , pair< in_state, front<s>::type >
+    , eval_if< 
+          apply_wrap2<p, second<_1>, _2>
+        , identity< first<_1> >
+        , apply_wrap2<in_op, first<_1>, _2>
+        >
+    >::type::first r;
+
+
+
+
+

Complexity

+

Linear. Performs exactly size<s>::value - 1 applications of pred, and at +most size<s>::value insertions.

+
+
+

Example

+
+typedef vector<int,float,float,char,int,int,int,double> types;
+typedef vector<double,int,char,float,int> expected;
+typedef reverse_unique< types, is_same<_1,_2> >::type result;
+
+BOOST_MPL_ASSERT(( equal< result,expected > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/reverse.html b/doc/refmanual/reverse.html new file mode 100644 index 0000000..e020830 --- /dev/null +++ b/doc/refmanual/reverse.html @@ -0,0 +1,114 @@ + + + + + + +The MPL Reference Manual: reverse + + + + + +
Front Page / Algorithms / Transformation Algorithms / reverse
+
+

reverse

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename In = unspecified
+    >
+struct reverse
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a reversed copy of the original sequence. reverse is a synonym for +reverse_copy.

+

[Note: This wording applies to a no-inserter version(s) of the algorithm. See the +Expression semantics subsection for a precise specification of the algorithm's +details in all cases — end note]

+
+
+

Header

+
+#include <boost/mpl/reverse.hpp>
+
+
+
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceA sequence to reverse.
InInserterAn inserter.
+
+
+

Expression semantics

+

For any Forward Sequence s, and an Inserter in:

+
+typedef reverse<s,in>::type r; 
+
+ +++ + + + + + +
Return type:A type.
Semantics:

Equivalent to

+
+typedef reverse_copy<s,in>::type r; 
+
+
+
+
+

Complexity

+

Linear.

+
+
+

Example

+
+typedef vector_c<int,9,8,7,6,5,4,3,2,1,0> numbers;
+typedef reverse< numbers >::type result;
+
+BOOST_MPL_ASSERT(( equal< result, range_c<int,0,10> > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/reversible-algorithm.html b/doc/refmanual/reversible-algorithm.html new file mode 100644 index 0000000..708e7e1 --- /dev/null +++ b/doc/refmanual/reversible-algorithm.html @@ -0,0 +1,188 @@ + + + + + + +The MPL Reference Manual: Reversible Algorithm + + + + + +
Front Page / Algorithms / Concepts / Reversible Algorithm
+
+

Reversible Algorithm

+
+

Description

+

A Reversible Algorithm is a member of a pair of +transformation algorithms that iterate over their input sequence(s) +in opposite directions. For each reversible +algorithm x there exists a counterpart algorithm reverse_x, +that exhibits the exact semantics of x except that the elements +of its input sequence argument(s) are processed in the reverse +order.

+
+
+

Expression requirements

+

In the following table and subsequent specifications, x is a placeholder token for the actual +Reversible Algorithm's name, s1,s2,...sn are +Forward Sequences, and in is an Inserter.

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionTypeComplexity
x<s1,s2,...sn, ...>::typeForward SequenceUnspecified.
x<s1,s2,...sn, ... in>::typeAny typeUnspecified.
reverse_x<s1,s2,...sn, ...>::typeForward SequenceUnspecified.
reverse_x<s1,s2,...sn, ... in>::typeAny typeUnspecified.
+
+
+

Expression semantics

+
+typedef x<s1,s2,...sn,...>::type t;
+
+ +++ + + + + + +
Precondition:s1 is an Extensible Sequence.
Semantics:

t is equivalent to

+
+x<
+      s1,s2,...sn,...
+    , back_inserter< clear<s1>::type >    
+    >::type
+
+

if has_push_back<s1>::value == true and

+
+reverse_x<
+      s1,s2,...sn,...
+    , front_inserter< clear<s1>::type >    
+    >::type
+
+

otherwise.

+
+ +
+typedef x<s1,s2,...sn,...in>::type t;
+
+ +++ + + + +
Semantics:t is the result of an x invocation with arguments +s1,s2,... sn,...in.
+ +
+typedef reverse_x<s1,s2,... sn,... >::type t;
+
+ +++ + + + + + +
Precondition:s1 is an Extensible Sequence.
Semantics:

t is equivalent to

+
+x<
+      s1,s2,...sn,...
+    , front_inserter< clear<s1>::type >    
+    >::type
+
+

if has_push_front<s1>::value == true and

+
+reverse_x<
+      s1,s2,...sn,...
+    , back_inserter< clear<s1>::type >    
+    >::type
+
+

otherwise.

+
+ +
+typedef reverse_x<s1,s2,...sn,... in>::type t;
+
+ +++ + + + +
Semantics:t is the result of a reverse_x invocation with arguments +s1,s2,...sn,...in.
+
+
+

Example

+
+typedef transform< 
+      range_c<int,0,10>
+    , plus<_1,int_<7> >
+    , back_inserter< vector0<> > 
+    >::type r1;
+
+typedef transform< r1, minus<_1,int_<2> > >::type r2;
+typedef reverse_transform< 
+      r2
+    , minus<_1,5> 
+    , front_inserter< vector0<> > 
+    >::type r3;
+
+BOOST_MPL_ASSERT(( equal<r1, range_c<int,7,17> > ));
+BOOST_MPL_ASSERT(( equal<r2, range_c<int,5,15> > ));
+BOOST_MPL_ASSERT(( equal<r3, range_c<int,0,10> > ));
+
+
+ + +
+ + + + + diff --git a/doc/refmanual/sequence-tag.html b/doc/refmanual/sequence-tag.html new file mode 100644 index 0000000..1987d40 --- /dev/null +++ b/doc/refmanual/sequence-tag.html @@ -0,0 +1,93 @@ + + + + + + +The MPL Reference Manual: sequence_tag + + + + + +
Front Page / Sequences / Intrinsic Metafunctions / sequence_tag
+
+

sequence_tag

+
+

Synopsis

+
+template<
+      typename X
+    >
+struct sequence_tag
+{
+    typedef unspecified type;
+};
+
+
+ + +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
XAny typeA type to obtain a sequence tag for.
+
+
+

Expression semantics

+

For any arbitrary type x:

+
+typedef sequence_tag<x>::type tag; 
+
+ +++ + + + + + +
Return type:A type.
Semantics:tag is an unspecified tag type for x.
+
+
+

Complexity

+

Amortized constant time.

+
+ +
+ + + + + diff --git a/doc/refmanual/sequences.html b/doc/refmanual/sequences.html new file mode 100644 index 0000000..ad28a3d --- /dev/null +++ b/doc/refmanual/sequences.html @@ -0,0 +1,44 @@ + + + + + + +The MPL Reference Manual: Sequences + + + + + +
Front Page / Sequences
+
+

Sequences

+

Compile-time sequences of types are one of the basic concepts of C++ +template metaprogramming. Differences in types of objects being +manipulated is the most common point of variability of similar, but +not identical designs, and these are a direct target for +metaprogramming. Templates were originally designed to address this +exact problem. However, without predefined mechanisms for +representing and manipulating sequences of types as opposed to +standalone template parameters, high-level template metaprogramming +is severely limited in its capabitilies.

+

The MPL recognizes the importance of type sequences as a fundamental +building block of many higher-level metaprogramming designs by +providing us with a conceptual framework for formal reasoning +and understanding of sequence properties, guarantees and +characteristics, as well as a first-class implementation of that +framework — a wealth of tools for concise, convenient, +conceptually precise and efficient sequence manipulation.

+ + +
+ + + + + diff --git a/doc/refmanual/set-c.html b/doc/refmanual/set-c.html new file mode 100644 index 0000000..5b51e91 --- /dev/null +++ b/doc/refmanual/set-c.html @@ -0,0 +1,124 @@ + + + + + + +The MPL Reference Manual: set_c + + + + + +
Front Page / Sequences / Classes / set_c
+
+

set_c

+
+

Description

+

set_c is an Integral Sequence Wrapper for set. As such, it shares +all set characteristics and requirements, and differs only in the way the +original sequence content is specified.

+
+
+

Header

+ ++++ + + + + + + + + + + + + + +
Sequence formHeader
Variadic#include <boost/mpl/set_c.hpp>
Numbered#include <boost/mpl/set/setn_c.hpp>
+
+ +
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in set.

+ + ++++ + + + + + + + + + + + + + + + + +
ExpressionSemantics
+set_c<T,c1,c2,... cn>
+setn_c<T,c1,c2,... cn>
+
+
A set of integral constant wrappers +integral_c<T,c1>, +integral_c<T,c2>, ... +integral_c<T,cn>; +see Integral Sequence Wrapper.
+set_c<T,c1,c2,... cn>::type
+setn_c<T,c1,c2,... cn>::type
+
+
Identical to setn< +integral_c<T,c1>, +integral_c<T,c2>, ... +integral_c<T,cn> >; +see Integral Sequence Wrapper.
+set_c<T,c1,c2,... cn>::value_type
+setn_c<T,c1,c2,... cn>::value_type
+
+
Identical to T; see +Integral Sequence Wrapper.
+
+
+

Example

+
+typedef set_c< int,1,3,5,7,9 > odds;
+
+BOOST_MPL_ASSERT_RELATION( size<odds>::value, ==, 5 );
+BOOST_MPL_ASSERT_NOT(( empty<odds> ));
+
+BOOST_MPL_ASSERT(( has_key< odds, integral_c<int,5> > ));
+BOOST_MPL_ASSERT_NOT(( has_key< odds, integral_c<int,4> > ));
+BOOST_MPL_ASSERT_NOT(( has_key< odds, integral_c<int,15> > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/set.html b/doc/refmanual/set.html new file mode 100644 index 0000000..02fae92 --- /dev/null +++ b/doc/refmanual/set.html @@ -0,0 +1,179 @@ + + + + + + +The MPL Reference Manual: set + + + + + +
Front Page / Sequences / Classes / set
+
+

set

+
+

Description

+

set is a variadic, associative, extensible sequence of types that +supports constant-time insertion and removal of elements, and testing for membership. +A set may contain at most one element for each key.

+
+
+

Header

+ ++++ + + + + + + + + + + + + + +
Sequence formHeader
Variadic#include <boost/mpl/set.hpp>
Numbered#include <boost/mpl/set/setn.hpp>
+
+ +
+

Expression semantics

+

In the following table, s is an instance of set, pos is an iterator into s, +and x, k, and t1,t2,... tn are arbitrary types.

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionSemantics
+set<t1,t2,... tn>
+setn<t1,t2,... tn>
+
+
set of elements t1,t2,... tn; see +Variadic Sequence.
+set<t1,t2,... tn>::type
+setn<t1,t2,... tn>::type
+
+
Identical to setn<t1,t2,... tn>; +see Variadic Sequence.
begin<s>::typeAn iterator pointing to the beginning of s; +see Associative Sequence.
end<s>::typeAn iterator pointing to the end of s; +see Associative Sequence.
size<s>::typeThe size of s; see Associative Sequence.
empty<s>::typeA boolean Integral Constant c such that +c::value == true if and only if s is empty; see +Associative Sequence.
front<s>::typeThe first element in s; see +Associative Sequence.
has_key<s,k>::typeA boolean Integral Constant c such that +c::value == true if and only if there is one or more elements +with the key k in s; see Associative Sequence.
count<s,k>::typeThe number of elements with the key k in s; +see Associative Sequence.
order<s,k>::typeA unique unsigned Integral Constant associated with +the key k in s; see Associative Sequence.
+at<s,k>::type
+at<s,k,def>::type
+
+
The element associated with the key k in +s; see Associative Sequence.
key_type<s,x>::typeIdentical to x; see Associative Sequence.
value_type<s,x>::typeIdentical to x; see Associative Sequence.
insert<s,x>::type

A new set equivalent to s except that

+
+at< t, key_type<s,x>::type >::type
+
+

is identical to value_type<s,x>::type.

+
insert<s,pos,x>::typeEquivalent to insert<s,x>::type; pos is ignored.
erase_key<s,k>::typeA new set equivalent to s except that +has_key<t, k>::value == false.
erase<s,pos>::typeEquivalent to erase<s, deref<pos>::type >::type.
clear<s>::typeAn empty set; see clear.
+
+
+

Example

+
+typedef set< int,long,double,int_<5> > s;
+
+BOOST_MPL_ASSERT_RELATION( size<s>::value, ==, 4 );
+BOOST_MPL_ASSERT_NOT(( empty<s> ));
+
+BOOST_MPL_ASSERT(( is_same< at<s,int>::type, int > ));
+BOOST_MPL_ASSERT(( is_same< at<s,long>::type, long > ));
+BOOST_MPL_ASSERT(( is_same< at<s,int_<5> >::type, int_<5> > ));
+BOOST_MPL_ASSERT(( is_same< at<s,char>::type, void_ > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/shift-left.html b/doc/refmanual/shift-left.html new file mode 100644 index 0000000..837d8c5 --- /dev/null +++ b/doc/refmanual/shift-left.html @@ -0,0 +1,146 @@ + + + + + + +The MPL Reference Manual: shift_left + + + + + +
Front Page / Metafunctions / Bitwise Operations / shift_left
+
+

shift_left

+
+

Synopsis

+
+template< 
+      typename T
+    , typename Shift
+    >
+struct shift_left
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the result of bitwise shift left (<<) operation on T.

+
+ + +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
TIntegral ConstantA value to shift.
ShiftUnsigned Integral ConstantA shift distance.
+

[Note: The requirements listed in this specification +are the ones imposed by the default implementation. See Numeric Metafunction concept +for the details on how to provide an implementation for a user-defined numeric type +that does not satisfy the Integral Constant requirements. — end note]

+
+
+

Expression semantics

+

For arbitrary Integral Constant c and unsigned Integral Constant shift:

+
+typedef shift_left<c,shift>::type r; 
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+typedef integral_c<
+      c::value_type
+    , ( c::value << shift::value )
+    > r;
+
+
+ +
+typedef shift_left<c,shift> r; 
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+struct r : shift_left<c,shift>::type {};
+
+
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef integral_c<unsigned,0> u0;
+typedef integral_c<unsigned,1> u1;
+typedef integral_c<unsigned,2> u2;
+typedef integral_c<unsigned,8> u8;
+
+BOOST_MPL_ASSERT_RELATION( (shift_left<u0,u0>::value), ==, 0 );
+BOOST_MPL_ASSERT_RELATION( (shift_left<u1,u0>::value), ==, 1 );
+BOOST_MPL_ASSERT_RELATION( (shift_left<u1,u1>::value), ==, 2 );
+BOOST_MPL_ASSERT_RELATION( (shift_left<u2,u1>::value), ==, 4 );
+BOOST_MPL_ASSERT_RELATION( (shift_left<u8,u1>::value), ==, 16 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/shift-right.html b/doc/refmanual/shift-right.html new file mode 100644 index 0000000..e1bfb65 --- /dev/null +++ b/doc/refmanual/shift-right.html @@ -0,0 +1,145 @@ + + + + + + +The MPL Reference Manual: shift_right + + + + + +
Front Page / Metafunctions / Bitwise Operations / shift_right
+
+

shift_right

+
+

Synopsis

+
+template< 
+      typename T
+    , typename Shift
+    >
+struct shift_right
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the result of bitwise shift right (>>) operation on T.

+
+ + +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
TIntegral ConstantA value to shift.
ShiftUnsigned Integral ConstantA shift distance.
+

[Note: The requirements listed in this specification +are the ones imposed by the default implementation. See Numeric Metafunction concept +for the details on how to provide an implementation for a user-defined numeric type +that does not satisfy the Integral Constant requirements. — end note]

+
+
+

Expression semantics

+

For arbitrary Integral Constant c and unsigned Integral Constant shift:

+
+typedef shift_right<c,shift>::type r; 
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+typedef integral_c<
+      c::value_type
+    , ( c::value >> shift::value )
+    > r;
+
+
+ +
+typedef shift_right<c,shift> r; 
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+struct r : shift_right<c,shift>::type {};
+
+
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef integral_c<unsigned,0> u0;
+typedef integral_c<unsigned,1> u1;
+typedef integral_c<unsigned,2> u2;
+typedef integral_c<unsigned,8> u8;
+
+BOOST_MPL_ASSERT_RELATION( (shift_right<u0,u0>::value), ==, 0 );
+BOOST_MPL_ASSERT_RELATION( (shift_right<u1,u0>::value), ==, 1 );
+BOOST_MPL_ASSERT_RELATION( (shift_right<u1,u1>::value), ==, 0 );
+BOOST_MPL_ASSERT_RELATION( (shift_right<u2,u1>::value), ==, 1 );
+BOOST_MPL_ASSERT_RELATION( (shift_right<u8,u1>::value), ==, 4 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/single-view.html b/doc/refmanual/single-view.html new file mode 100644 index 0000000..b71e146 --- /dev/null +++ b/doc/refmanual/single-view.html @@ -0,0 +1,123 @@ + + + + + + +The MPL Reference Manual: single_view + + + + + +
Front Page / Sequences / Views / single_view
+
+

single_view

+
+

Synopsis

+
+template<
+      typename T
+    >
+struct single_view
+{
+    // unspecified
+    // ...
+};
+
+
+
+

Description

+

A view onto an arbitrary type T as on a single-element sequence.

+
+ + +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
TAny typeThe type to be wrapped in a sequence.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Random Access Sequence.

+

In the following table, v is an instance of single_view, x is an arbitrary type.

+ ++++ + + + + + + + + + + + + + +
ExpressionSemantics
+single_view<x>
+single_view<x>::type
+
+
A single-element Random Access Sequence v such that +front<v>::type is identical to x.
size<v>::typeThe size of v; size<v>::value == 1; +see Random Access Sequence.
+
+
+

Example

+
+typedef single_view<int> view;
+typedef begin<view>::type first;
+typedef end<view>::type last;
+
+BOOST_MPL_ASSERT(( is_same< deref<first>::type,int > ));
+BOOST_MPL_ASSERT(( is_same< next<first>::type,last > ));
+BOOST_MPL_ASSERT(( is_same< prior<last>::type,first > ));
+
+BOOST_MPL_ASSERT_RELATION( size<view>::value, ==, 1 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/size-t.html b/doc/refmanual/size-t.html new file mode 100644 index 0000000..fca7032 --- /dev/null +++ b/doc/refmanual/size-t.html @@ -0,0 +1,112 @@ + + + + + + +The MPL Reference Manual: size_t + + + + + +
Front Page / Data Types / Numeric / size_t
+
+

size_t

+
+

Synopsis

+
+template<
+      std::size_t N
+    >
+struct size_t
+{
+    // unspecified
+    // ...
+};
+
+
+
+

Description

+

An Integral Constant wrapper for std::size_t.

+
+
+

Header

+
+#include <boost/mpl/size_t.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
NAn integral constantA value to wrap.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Integral Constant.

+

For arbitrary integral constant n:

+ ++++ + + + + + + + + + + +
ExpressionSemantics
size_t<c>An Integral Constant x such that x::value == c +and x::value_type is identical to std::size_t.
+
+
+

Example

+
+typedef size_t<8> eight;
+
+BOOST_MPL_ASSERT(( is_same< eight::value_type, std::size_t > ));
+BOOST_MPL_ASSERT(( is_same< eight::type, eight > ));
+BOOST_MPL_ASSERT(( is_same< next< eight >::type, size_t<9> > ));
+BOOST_MPL_ASSERT(( is_same< prior< eight >::type, size_t<7> > ));
+BOOST_MPL_ASSERT_RELATION( (eight::value), ==, 8 );
+assert( eight() == 8 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/size.html b/doc/refmanual/size.html new file mode 100644 index 0000000..eddf285 --- /dev/null +++ b/doc/refmanual/size.html @@ -0,0 +1,120 @@ + + + + + + +The MPL Reference Manual: size + + + + + +
Front Page / Sequences / Intrinsic Metafunctions / size
+
+

size

+
+

Synopsis

+
+template<
+      typename Sequence
+    >
+struct size
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

size returns the number of elements in the sequence, that is, the number of elements +in the range [begin<Sequence>::type, end<Sequence>::type).

+
+
+

Header

+
+#include <boost/mpl/size.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceA sequence to query.
+
+
+

Expression semantics

+

For any Forward Sequence s:

+
+typedef size<s>::type n; 
+
+ +++ + + + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+typedef distance< begin<s>::type,end<s>::type >::type n;
+
+
Postcondition:n::value >= 0.
+
+
+

Complexity

+

The complexity of the size metafunction directly depends on the implementation of +the particular sequence it is applied to. In the worst case, size guarantees a +linear complexity.

+

If the s is a Random Access Sequence, size<s>::type is an O(1) operation. +The opposite is not necessarily true — for example, a sequence class that models +Forward Sequence might still give us an O(1) size implementation.

+
+
+

Example

+
+typedef list0<> empty_list;
+typedef vector_c<int,0,1,2,3,4,5> numbers;
+typedef range_c<int,0,100> more_numbers;
+
+BOOST_MPL_ASSERT_RELATION( size<list>::value, ==, 0 );
+BOOST_MPL_ASSERT_RELATION( size<numbers>::value, ==, 5 );
+BOOST_MPL_ASSERT_RELATION( size<more_numbers>::value, ==, 100 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/sizeof.html b/doc/refmanual/sizeof.html new file mode 100644 index 0000000..726f94b --- /dev/null +++ b/doc/refmanual/sizeof.html @@ -0,0 +1,113 @@ + + + + + + +The MPL Reference Manual: sizeof_ + + + + + +
Front Page / Metafunctions / Miscellaneous / sizeof_
+
+

sizeof_

+
+

Synopsis

+
+template<
+      typename X
+    >
+struct sizeof_
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the result of a sizeof(X) expression wrapped into an +Integral Constant of the corresponding type, std::size_t.

+
+
+

Header

+
+#include <boost/mpl/sizeof.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
XAny typeA type to compute the sizeof for.
+
+
+

Expression semantics

+

For an arbitrary type x:

+
+typedef sizeof_<x>::type n; 
+
+ +++ + + + + + + + +
Return type:Integral Constant.
Precondition:x is a complete type.
Semantics:

Equivalent to

+
+typedef size_t< sizeof(x) > n;
+
+
+
+
+

Complexity

+

Constant time.

+
+
+

Example

+
+struct udt { char a[100]; };
+
+BOOST_MPL_ASSERT_RELATION( sizeof_<char>::value, ==, sizeof(char) );
+BOOST_MPL_ASSERT_RELATION( sizeof_<int>::value, ==, sizeof(int) );
+BOOST_MPL_ASSERT_RELATION( sizeof_<double>::value, ==, sizeof(double) );
+BOOST_MPL_ASSERT_RELATION( sizeof_<udt>::value, ==, sizeof(my) );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/sort.html b/doc/refmanual/sort.html new file mode 100644 index 0000000..3ebc8d2 --- /dev/null +++ b/doc/refmanual/sort.html @@ -0,0 +1,151 @@ + + + + + + +The MPL Reference Manual: sort + + + + + +
Front Page / Algorithms / Transformation Algorithms / sort
+
+

sort

+
+

Synopsis

+
+template<
+      typename Seq
+    , typename Pred = less<_1,_2>
+    , typename In = unspecified
+    >
+struct sort
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a new sequence of all elements in the range [begin<Seq>::type, end<Seq>::type) sorted according +to the ordering relation Pred.

+

[Note: This wording applies to a no-inserter version(s) of the algorithm. See the +Expression semantics subsection for a precise specification of the algorithm's +details in all cases — end note]

+
+
+

Header

+
+#include <boost/mpl/sort.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SeqForward SequenceAn original sequence.
PredBinary Lambda ExpressionAn ordering relation.
InInserterAn inserter.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Reversible Algorithm.

+

For any Forward Sequence s, a binary Lambda Expression pred, and an +Inserter in:

+
+typedef sort<s,pred,in>::type r;
+
+ +++ + + + + + +
Return type:A type.
Semantics:

If size<s>::value <= 1, equivalent to

+
+typedef copy<s,in>::type r;
+
+

otherwise equivalent to

+
+typedef back_inserter< vector<> > aux_in;
+typedef lambda<pred>::type p;
+
+typedef begin<s>::type pivot;
+typedef partition<
+      iterator_range< next<pivot>::type, end<s>::type >
+    , apply_wrap2<p,_1,deref<pivot>::type>
+    , aux_in
+    , aux_in
+    >::type partitioned;
+
+typedef sort<partitioned::first,p,aux_in >::type part1;
+typedef sort<partitioned::second,p,aux_in >::type part2;
+
+typedef copy<
+      joint_view< 
+          joint_view<part1,single_view< deref<pivot>::type > >
+        , part2
+        >
+    , in
+    >::type r;
+
+
+
+
+

Complexity

+

Average O(n log(n)) where n == size<s>::value, quadratic at worst.

+
+
+

Example

+
+typedef vector_c<int,3,4,0,-5,8,-1,7> numbers;
+typedef vector_c<int,-5,-1,0,3,4,7,8> expected;
+typedef sort<numbers>::type result;
+
+BOOST_MPL_ASSERT(( equal< result, expected, equal_to<_,_> > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/stable-partition.html b/doc/refmanual/stable-partition.html new file mode 100644 index 0000000..89bbf16 --- /dev/null +++ b/doc/refmanual/stable-partition.html @@ -0,0 +1,149 @@ + + + + + + +The MPL Reference Manual: stable_partition + + + + + +
Front Page / Algorithms / Transformation Algorithms / stable_partition
+
+

stable_partition

+
+

Synopsis

+
+template<
+      typename Seq
+    , typename Pred
+    , typename In1 = unspecified
+    , typename In2 = unspecified
+    >
+struct stable_partition
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a pair of sequences together containing all elements in the range +[begin<Seq>::type, end<Seq>::type) split into two groups based on the predicate Pred. +stable_partition is guaranteed to preserve the relative order of the +elements in the resulting sequences.

+

[Note: This wording applies to a no-inserter version(s) of the algorithm. See the +Expression semantics subsection for a precise specification of the algorithm's +details in all cases — end note]

+
+ + +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SeqForward SequenceAn original sequence.
PredUnary Lambda ExpressionA partitioning predicate.
In1, In2InserterOutput inserters.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Reversible Algorithm.

+

For any Forward Sequence s, an unary Lambda Expression pred, and Inserters +in1 and in2:

+
+typedef stable_partition<s,pred,in1,in2>::type r;
+
+ +++ + + + + + +
Return type:A pair.
Semantics:

Equivalent to

+
+typedef lambda<pred>::type p;
+typedef lambda<in1::operation>::type in1_op;
+typedef lambda<in2::operation>::type in2_op;
+
+typedef fold<
+      s
+    , pair< in1::state, in2::state >
+    , if_< 
+          apply_wrap1<p,_2>
+        , pair< apply_wrap2<in1_op,first<_1>,_2>, second<_1> >
+        , pair< first<_1>, apply_wrap2<in2_op,second<_1>,_2> >
+        >
+    >::type r;
+
+
+
+
+

Complexity

+

Linear. Exactly size<s>::value applications of pred, and size<s>::value +of summarized in1::operation / in2::operation applications.

+
+
+

Example

+
+template< typename N > struct is_odd : bool_<(N::value % 2)> {};
+
+typedef stable_partition<
+      range_c<int,0,10> 
+    , is_odd<_1>
+    , back_inserter< vector<> >
+    , back_inserter< vector<> >
+    >::type r;
+
+BOOST_MPL_ASSERT(( equal< r::first, vector_c<int,1,3,5,7,9> > ));
+BOOST_MPL_ASSERT(( equal< r::second, vector_c<int,0,2,4,6,8> > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/tag-dispatched.html b/doc/refmanual/tag-dispatched.html new file mode 100644 index 0000000..040a2a0 --- /dev/null +++ b/doc/refmanual/tag-dispatched.html @@ -0,0 +1,171 @@ + + + + + + +The MPL Reference Manual: Tag Dispatched Metafunction + + + + + +
Front Page / Metafunctions / Concepts / Tag Dispatched Metafunction
+
+

Tag Dispatched Metafunction

+
+

Summary

+

A Tag Dispatched Metafunction is a Metafunction that employs a +tag dispatching technique in its implementation to build an +infrastructure for easy overriding/extenstion of the metafunction's +behavior.

+
+
+

Notation

+ ++++ + + + + + + + + + + + + + + + + +
SymbolLegend
nameA placeholder token for the specific metafunction's name.
tag-metafunctionA placeholder token for the tag metafunction's name.
tagA placeholder token for one of possible tag types +returned by the tag metafunction.
+
+
+

Synopsis

+
+template< typename Tag > struct name_impl; 
+
+template<
+      typename X
+    [, ...]
+    >
+struct name
+    : name_impl< typename tag-metafunction<X>::type >
+        ::template apply<X [, ...]>
+{
+};
+
+template< typename Tag > struct name_impl
+{
+    template< typename X [, ...] > struct apply
+    {
+        // default implementation
+    };
+};
+
+template<> struct name_impl<tag>
+{
+    template< typename X [, ...] > struct apply
+    {
+        // tag-specific implementation
+    };
+};
+
+
+
+

Description

+

The usual mechanism for overriding a metafunction's behavior is class +template specialization — given a library-defined metafunction f, +it's possible to write a specialization of f for a specific type +user_type that would have the required semantics [4].

+

While this mechanism is always available, it's not always the most +convenient one, especially if it is desirable to specialize a +metafunction's behavior for a family of related types. A typical +example of it is numbered forms of sequence classes in MPL itself +(list0, ..., list50, et al.), and sequence classes in general.

+

A Tag Dispatched Metafunction is a concept name for an instance of +the metafunction implementation infrastructure being employed by the +library to make it easier for users and implementors to override the +behavior of library's metafunctions operating on families of specific +types.

+

The infrastructure is built on a variation of the technique commonly +known as tag dispatching (hence the concept name), +and involves three entities: a metafunction itself, an associated +tag-producing tag metafunction, and the metafunction's +implementation, in the form of a Metafunction Class template +parametrized by a Tag type parameter. The metafunction redirects +to its implementation class template by invoking its specialization +on a tag type produced by the tag metafunction with the original +metafunction's parameters.

+ + + + + +
[4]Usually such user-defined specialization is still required +to preserve the f's original invariants and complexity requirements.
+
+
+

Example

+
+#include <boost/mpl/size.hpp>
+
+namespace user {
+
+struct bitset_tag;
+
+struct bitset0
+{
+    typedef bitset_tag tag;
+    // ...
+};
+
+template< typename B0 > struct bitset1
+{
+    typedef bitset_tag tag;
+    // ...
+};
+
+template< typename B0, ..., typename Bn > struct bitsetn
+{
+    typedef bitset_tag tag;
+    // ...
+};
+
+} // namespace user
+
+namespace boost { namespace mpl {
+template<> struct size_impl<user::bitset_tag>
+{
+    template< typename Bitset > struct apply
+    {
+        typedef typename Bitset::size type;
+    };
+};
+}}
+
+
+ + +
+ + + + + diff --git a/doc/refmanual/terminology.html b/doc/refmanual/terminology.html new file mode 100644 index 0000000..90950b1 --- /dev/null +++ b/doc/refmanual/terminology.html @@ -0,0 +1,51 @@ + + + + + + +The MPL Reference Manual: Terminology + + + + + +
Front Page / Terminology
+
+

Terminology

+
+
Overloaded name
+
Overloaded name is a term used in this reference documentation to designate +a metafunction providing more than one public interface. In reality, +class template overloading is nonexistent and the referenced functionality +is implemented by other, unspecified, means.
+
+
+
Concept-identical
+
A sequence s1 is said to be concept-identical to a sequence s2 if +s1 and s2 model the exact same set of concepts.
+
+
+
Bind expression
+

A bind expression is simply that — an instantiation of one of the bind +class templates. For instance, these are all bind expressions:

+
+bind< quote3<if_>, _1,int,long >
+bind< _1, bind< plus<>, int_<5>, _2> >
+bind< times<>, int_<2>, int_<2> >
+
+

and these are not:

+
+if_< _1, bind< plus<>, int_<5>, _2>, _2 >        
+protect< bind< quote3<if_>, _1,int,long > >
+_2
+
+
+
+ +
+ + + + + diff --git a/doc/refmanual/times.html b/doc/refmanual/times.html new file mode 100644 index 0000000..24baf01 --- /dev/null +++ b/doc/refmanual/times.html @@ -0,0 +1,140 @@ + + + + + + +The MPL Reference Manual: times + + + + + +
Front Page / Metafunctions / Arithmetic Operations / times
+
+

times

+
+

Synopsis

+
+template<
+      typename T1
+    , typename T2
+    , typename T3 = unspecified
+    ...
+    , typename Tn = unspecified
+    >
+struct times
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the product of its arguments.

+
+
+

Header

+
+#include <boost/mpl/times.hpp>
+#include <boost/mpl/arithmetic.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
T1, T2,... TnIntegral ConstantOperation's arguments.
+

[Note: The requirements listed in this specification +are the ones imposed by the default implementation. See Numeric Metafunction concept +for the details on how to provide an implementation for a user-defined numeric type +that does not satisfy the Integral Constant requirements. — end note]

+
+
+

Expression semantics

+

For any Integral Constants c1,c2,... cn:

+
+typedef times<c1,...cn>::type r; 
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+typedef integral_c<
+      typeof(c1::value * c2::value)
+    , ( c1::value * c2::value )
+    > c;
+    
+typedef times<c,c3,...cn>::type r; 
+
+
+ +
+typedef times<c1,...cn> r;
+
+ +++ + + + + + +
Return type:Integral Constant.
Semantics:

Equivalent to

+
+struct r : times<c1,...cn>::type {};
+
+
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef times< int_<-10>, int_<3>, long_<1> >::type r;
+BOOST_MPL_ASSERT_RELATION( r::value, ==, -30 );
+BOOST_MPL_ASSERT(( is_same< r::value_type, long > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/transform-view.html b/doc/refmanual/transform-view.html new file mode 100644 index 0000000..5602625 --- /dev/null +++ b/doc/refmanual/transform-view.html @@ -0,0 +1,130 @@ + + + + + + +The MPL Reference Manual: transform_view + + + + + +
Front Page / Sequences / Views / transform_view
+
+

transform_view

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename F
+    >
+struct transform_view
+{
+    // unspecified
+    // ...
+};
+
+
+
+

Description

+

A view the full range of Sequence's transformed elements.

+
+ + +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceA sequence to wrap.
FUnary Lambda ExpressionA transformation.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Forward Sequence.

+

In the following table, v is an instance of transform_view, s is an arbitrary +Forward Sequence, and f is an unary Lambda Expression.

+ ++++ + + + + + + + + + + + + + +
ExpressionSemantics
+transform_view<s,f>
+transform_view<s,f>::type
+
+
A lazy Forward Sequence such that for each i in the +range [begin<v>::type, end<v>::type) and each j in for in the range +[begin<s>::type, end<s>::type) deref<i>::type is identical to +apply< f, deref<j>::type >::type.
size<v>::typeThe size of v; +size<v>::value == size<s>::value; +linear complexity; see Forward Sequence.
+
+
+

Example

+

Find the largest type in a sequence.

+
+typedef vector<int,long,char,char[50],double> types;
+typedef max_element<
+      transform_view< types, size_of<_> >
+    >::type iter;
+
+BOOST_MPL_ASSERT_RELATION( deref<iter>::type::value, ==, 50 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/transform.html b/doc/refmanual/transform.html new file mode 100644 index 0000000..8efb77e --- /dev/null +++ b/doc/refmanual/transform.html @@ -0,0 +1,183 @@ + + + + + + +The MPL Reference Manual: transform + + + + + +
Front Page / Algorithms / Transformation Algorithms / transform
+
+

transform

+
+

Synopsis

+
+template<
+      typename Seq
+    , typename Op
+    , typename In = unspecified
+    >
+struct transform
+{
+    typedef unspecified type;
+};
+
+template<
+      typename Seq1
+    , typename Seq2
+    , typename BinaryOp
+    , typename In = unspecified
+    >
+struct transform
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

transform is an overloaded name:

+
    +
  • transform<Seq,Op> returns a transformed copy of the original sequence +produced by applying an unary transformation Op to every element +in the [begin<Sequence>::type, end<Sequence>::type) range.
  • +
  • transform<Seq1,Seq2,Op> returns a new sequence produced by applying a +binary transformation BinaryOp to a pair of elements (e1, e21) +from the corresponding [begin<Seq1>::type, end<Seq1>::type) and [begin<Seq2>::type, end<Seq2>::type) ranges.
  • +
+

[Note: This wording applies to a no-inserter version(s) of the algorithm. See the +Expression semantics subsection for a precise specification of the algorithm's +details in all cases — end note]

+
+
+

Header

+
+#include <boost/mpl/transform.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
Sequence, +Seq1, Seq2Forward SequenceSequences to transform.
Op, +BinaryOpLambda ExpressionA transformation.
InInserterAn inserter.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Reversible Algorithm.

+

For any Forward Sequences s, s1 and s2, Lambda Expressions op and op2, +and an Inserter in:

+
+typedef transform<s,op,in>::type r; 
+
+ +++ + + + + + +
Return type:A type.
Postcondition:

Equivalent to

+
+typedef lambda<op>::type f;
+typedef lambda<in::operation>::type in_op;
+
+typedef fold< 
+      s
+    , in::state
+    , bind< in_op, _1, bind<f, _2> > 
+    >::type r;
+
+
+
+typedef transform<s1,s2,op,in>::type r; 
+
+ +++ + + + + + +
Return type:A type.
Postcondition:

Equivalent to

+
+typedef lambda<op2>::type f;
+typedef lambda<in::operation>::type in_op;
+
+typedef fold< 
+      pair_view<s1,s2>
+    , in::state
+    , bind< 
+          in_op
+        , _1
+        , bind<f, bind<first<>,_2>, bind<second<>,_2> >
+        > 
+    >::type r;
+
+
+
+
+

Complexity

+

Linear. Exactly size<s>::value / size<s1>::value applications of +op / op2 and in::operation.

+
+
+

Example

+
+typedef vector<char,short,int,long,float,double> types;
+typedef vector<char*,short*,int*,long*,float*,double*> pointers;
+typedef transform< types,boost::add_pointer<_1> >::type result;
+
+BOOST_MPL_ASSERT(( equal<result,pointers> ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/transformation-algorithms.html b/doc/refmanual/transformation-algorithms.html new file mode 100644 index 0000000..57aff8c --- /dev/null +++ b/doc/refmanual/transformation-algorithms.html @@ -0,0 +1,62 @@ + + + + + + +The MPL Reference Manual: Transformation Algorithms + + + + + +
Front Page / Algorithms / Transformation Algorithms
+
+

Transformation Algorithms

+

According to their name, MPL's transformation, or sequence-building +algorithms provide the tools for building new sequences from the existing +ones by performing some kind of transformation. A typical transformation +alogrithm takes one or more input sequences and a transformation +metafunction/predicate, and returns a new sequence built according to the +algorithm's semantics through the means of its Inserter argument, which +plays a role similar to the role of run-time Output Iterator.

+ +

Every transformation algorithm is a Reversible Algorithm, providing +an accordingly named reverse_ counterpart carrying the transformation +in the reverse order. Thus, all sequence-building algorithms come in pairs, +for instance replace / reverse_replace. In presence of variability of +the output sequence's properties such as front or backward extensibility, +the existence of the bidirectional algorithms allows for the most efficient +way to perform the required transformation.

+ + + +
+ + + + + diff --git a/doc/refmanual/trivial-metafunction.html b/doc/refmanual/trivial-metafunction.html new file mode 100644 index 0000000..e9d1eae --- /dev/null +++ b/doc/refmanual/trivial-metafunction.html @@ -0,0 +1,84 @@ + + + + + + +The MPL Reference Manual: Trivial Metafunction + + + + + +
Front Page / Metafunctions / Concepts / Trivial Metafunction
+
+

Trivial Metafunction

+
+

Description

+

A Trivial Metafunction accepts a single argument of a class type x and +returns the x's nested type member x::name, where name is +a placeholder token for the actual member's name accessed by a specific +metafunction's instance. By convention, all trivial metafunctions in MPL +are named after the members they provide assess to. For instance, a Trivial Metafunction named first reaches for the x's nested member +::first.

+
+
+

Expression requirements

+

In the following table and subsequent specifications, name is placeholder token for the names of +the Trivial Metafunction itself and the accessed member, and x is +a class type such that x::name is a valid type-name.

+ +++++ + + + + + + + + + + + + +
ExpressionTypeComplexity
name<x>::typeAny typeConstant time.
+
+
+

Expression semantics

+
+typedef name<x>::type r;
+
+ +++ + + + + + +
Precondition:x::name is a valid type-name.
Semantics:is_same<r,x::name>::value == true.
+
+
+

Models

+ +
+ +
+ + + + + diff --git a/doc/refmanual/trivial-metafunctions.html b/doc/refmanual/trivial-metafunctions.html new file mode 100644 index 0000000..3bbfba1 --- /dev/null +++ b/doc/refmanual/trivial-metafunctions.html @@ -0,0 +1,49 @@ + + + + + + +The MPL Reference Manual: Trivial Metafunctions Summary + + + + + +
Front Page / Metafunctions / Trivial / Trivial Metafunctions Summary
+
+

Trivial Metafunctions Summary

+

In the following table, x is an arbitrary class type.

+ ++++ + + + + + + + + + + + + + + + + +
MetafunctionHeader
first<x>::type#include <boost/mpl/pair.hpp>
second<x>::type#include <boost/mpl/pair.hpp>
base<x>::type#include <boost/mpl/base.hpp>
+ +
+ + + + + diff --git a/doc/refmanual/trivial.html b/doc/refmanual/trivial.html new file mode 100644 index 0000000..0fb90bf --- /dev/null +++ b/doc/refmanual/trivial.html @@ -0,0 +1,33 @@ + + + + + + +The MPL Reference Manual: Trivial + + + + + +
Front Page / Metafunctions / Trivial
+
+

Trivial

+

The MPL provides a number of Trivial Metafunctions that a nothing more than +thin wrappers for a differently-named class nested type members. While important +in the context of in-place metafunction composition, these metafunctions have +so little to them that presenting them in the same format as the rest of the +compoments in this manual would result in more boilerplate syntactic baggage than +the actual content. To avoid this problem, we instead factor out the common +metafunctions' requirements into the corresponding concept and gather all of +them in a single place — this subsection — in a compact table form that is +presented below.

+ +
+ + + + + diff --git a/doc/refmanual/type-selection.html b/doc/refmanual/type-selection.html new file mode 100644 index 0000000..1a77abf --- /dev/null +++ b/doc/refmanual/type-selection.html @@ -0,0 +1,29 @@ + + + + + + +The MPL Reference Manual: Type Selection + + + + + +
Front Page / Metafunctions / Type Selection
+ + + + + + diff --git a/doc/refmanual/unique.html b/doc/refmanual/unique.html new file mode 100644 index 0000000..909e3a6 --- /dev/null +++ b/doc/refmanual/unique.html @@ -0,0 +1,148 @@ + + + + + + +The MPL Reference Manual: unique + + + + + +
Front Page / Algorithms / Transformation Algorithms / unique
+
+

unique

+
+

Synopsis

+
+template<
+      typename Seq
+    , typename Pred
+    , typename In = unspecified
+    >
+struct unique
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns a sequence of the initial elements of every subrange of the +original sequence Seq whose elements are all the same.

+

[Note: This wording applies to a no-inserter version(s) of the algorithm. See the +Expression semantics subsection for a precise specification of the algorithm's +details in all cases — end note]

+
+
+

Header

+
+#include <boost/mpl/unique.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceAn original sequence.
PredBinary Lambda ExpressionAn equivalence relation.
InInserterAn inserter.
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Reversible Algorithm.

+

For any Forward Sequence s, a binary Lambda Expression pred, +and an Inserter in:

+
+typedef unique<s,pred,in>::type r; 
+
+ +++ + + + + + +
Return type:A type.
Semantics:

If size<s>::value <= 1, then equivalent to

+
+typedef copy<s,in>::type r;
+
+

otherwise equivalent to

+
+typedef lambda<pred>::type p;
+typedef lambda<in::operation>::type in_op;
+typedef apply_wrap2<
+      in_op
+    , in::state
+    , front<types>::type 
+    >::type in_state;
+
+typedef fold<
+      s
+    , pair< in_state, front<s>::type >
+    , eval_if< 
+          apply_wrap2<p, second<_1>, _2>
+        , identity< first<_1> >
+        , apply_wrap2<in_op, first<_1>, _2>
+        >
+    >::type::first r;
+
+
+
+
+

Complexity

+

Linear. Performs exactly size<s>::value - 1 applications of pred, and at +most size<s>::value insertions.

+
+
+

Example

+
+typedef vector<int,float,float,char,int,int,int,double> types;
+typedef vector<int,float,char,int,double> expected;
+typedef unique< types, is_same<_1,_2> >::type result;
+
+BOOST_MPL_ASSERT(( equal< result,expected > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/unpack-args.html b/doc/refmanual/unpack-args.html new file mode 100644 index 0000000..73d8cde --- /dev/null +++ b/doc/refmanual/unpack-args.html @@ -0,0 +1,110 @@ + + + + + + +The MPL Reference Manual: unpack_args + + + + + +
Front Page / Metafunctions / Invocation / unpack_args
+
+

unpack_args

+
+

Synopsis

+
+template< 
+      typename F
+    >
+struct unpack_args
+{
+    // unspecified
+    // ...
+};
+
+
+
+

Description

+

A higher-order primitive transforming an n-ary Lambda Expression F into +an unary Metafunction Class g accepting a single sequence of n arguments.

+
+ + +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
FLambda ExpressionA lambda expression to adopt.
+
+
+

Expression semantics

+

For an arbitrary Lambda Expression f, and arbitrary types a1,... an:

+
+typedef unpack_args<f> g;
+
+ +++ + + + + + +
Return type:Metafunction Class.
Semantics:

g is a unary Metafunction Class such that

+
+apply_wrapn< g, vector<a1,...an> >::type
+
+

is identical to

+
+apply<F,a1,...an>::type
+
+
+
+
+

Example

+
+BOOST_MPL_ASSERT(( apply< 
+      unpack_args< is_same<_1,_2> >
+    , vector<int,int>
+    > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/upper-bound.html b/doc/refmanual/upper-bound.html new file mode 100644 index 0000000..b5537b1 --- /dev/null +++ b/doc/refmanual/upper-bound.html @@ -0,0 +1,125 @@ + + + + + + +The MPL Reference Manual: upper_bound + + + + + +
Front Page / Algorithms / Querying Algorithms / upper_bound
+
+

upper_bound

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename T
+    , typename Pred = less<_1,_2>
+    >
+struct upper_bound
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the last position in the sorted Sequence where T could be inserted without +violating the ordering.

+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceForward SequenceA sorted sequence to search in.
TAny typeA type to search a position for.
PredBinary Lambda ExpressionA search criteria.
+
+
+

Expression semantics

+

For any sorted Forward Sequence s, binary Lambda Expression pred, and +arbitrary type x:

+
+typedef upper_bound< s,x,pred >::type i; 
+
+ +++ + + + + + +
Return type:Forward Iterator
Semantics:

i is the furthermost iterator in [begin<s>::type, end<s>::type) such that, for every iterator +j in [begin<s>::type, i),

+
+apply< pred, x, deref<j>::type >::type::value == false 
+
+
+
+
+

Complexity

+

The number of comparisons is logarithmic: at most log2( size<s>::value ) + 1. +If s is a Random Access Sequence then the number of steps through the range +is also logarithmic; otherwise, the number of steps is proportional to +size<s>::value.

+
+
+

Example

+
+typedef vector_c<int,1,2,3,3,3,5,8> numbers;
+typedef upper_bound< numbers, int_<3> >::type iter;
+
+BOOST_MPL_ASSERT_RELATION(
+      (distance< begin<numbers>::type,iter >::value), ==, 5
+    );
+
+BOOST_MPL_ASSERT_RELATION( deref<iter>::type::value, ==, 5 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/value-type.html b/doc/refmanual/value-type.html new file mode 100644 index 0000000..b174f61 --- /dev/null +++ b/doc/refmanual/value-type.html @@ -0,0 +1,125 @@ + + + + + + +The MPL Reference Manual: value_type + + + + + +
Front Page / Sequences / Intrinsic Metafunctions / value_type
+
+

value_type

+
+

Synopsis

+
+template<
+      typename Sequence
+    , typename X
+    >
+struct value_type
+{
+    typedef unspecified type;
+};
+
+
+
+

Description

+

Returns the value that would be used for element X in Sequence.

+
+
+

Header

+
+#include <boost/mpl/value_type.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + + + + + +
ParameterRequirementDescription
SequenceAssociative SequenceA sequence to query.
XAny typeThe type to get the value for.
+
+
+

Expression semantics

+

For any Associative Sequence s, and an artibrary type x:

+
+typedef value_type<s,x>::type v; 
+
+ +++ + + + + + + + + + +
Return type:A type.
Precondition:x can be put in s.
Semantics:v is the value that would be used for x in s.
Postcondition:

If +.. parsed-literal:

+
+has_key< s,key_type<s,x>::type >::type
+
+

then +.. parsed-literal:

+
+at< s,key_type<s,x>::type >::type
+
+

is identical to value_type<s,x>::type.

+
+
+
+

Complexity

+

Amortized constant time.

+
+
+

Example

+
+typedef value_type< map<>,pair<int,unsigned> >::type v1;
+typedef value_type< set<>,pair<int,unsigned> >::type v2;
+
+BOOST_MPL_ASSERT(( is_same< v1,unsigned > ));
+BOOST_MPL_ASSERT(( is_same< v2,pair<int,unsigned> > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/variadic-sequence.html b/doc/refmanual/variadic-sequence.html new file mode 100644 index 0000000..444d525 --- /dev/null +++ b/doc/refmanual/variadic-sequence.html @@ -0,0 +1,135 @@ + + + + + + +The MPL Reference Manual: Variadic Sequence + + + + + +
Front Page / Sequences / Concepts / Variadic Sequence
+
+

Variadic Sequence

+
+

Description

+

A Variadic Sequence is a member of a family of sequence classes with both +variadic and numbered forms. If seq is a generic name for some +Variadic Sequence, its variadic form allows us to specify a sequence of +n elements t1,t2,... tn, for any n from 0 up to a +preprocessor-configurable limit BOOST_MPL_LIMIT_seq_SIZE, +using the following notation:

+
+
+
seq<t1,t2,... tn>
+
+
+

By contrast, each numbered sequence form accepts the exact number of elements +that is encoded in the name of the corresponding class template:

+
+
+
seqn<t1,t2,... tn>
+
+
+

For numbered forms, there is no predefined top limit for n, aside from compiler +limitations on the number of template parameters.

+ +
+
+

Expression requirements

+

In the following table and subsequent specifications, seq is a placeholder token for the actual +Variadic Sequence name.

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionTypeComplexity
seq<t1,t2,... tn>Forward SequenceAmortized constant time
seq<t1,t2,... tn>::typeForward SequenceAmortized constant time
seqn<t1,t2,... tn>Forward SequenceAmortized constant time
seqn<t1,t2,... tn>::typeForward SequenceAmortized constant time
+
+
+

Expression semantics

+
+typedef seq<t1,t2,... tn> s;
+typedef seqn<t1,t2,... tn> s;
+
+ +++ + + + + + +
Semantics:s is a sequence of elements t1,t2,... tn.
Postcondition:

size<s>::value == n.

+ +
+ +
+typedef seq<t1,t2,... tn>::type s;
+typedef seqn<t1,t2,... tn>::type s;
+
+ +++ + + + + + +
Semantics:s is identical to seqn<t1,t2,... tn >.
Postcondition:size<s>::value == n.
+
+
+

Models

+ +
+ +
+ + + + + diff --git a/doc/refmanual/vector-c.html b/doc/refmanual/vector-c.html new file mode 100644 index 0000000..ace7756 --- /dev/null +++ b/doc/refmanual/vector-c.html @@ -0,0 +1,125 @@ + + + + + + +The MPL Reference Manual: vector_c + + + + + +
Front Page / Sequences / Classes / vector_c
+
+

vector_c

+
+

Description

+

vector_c is an Integral Sequence Wrapper for vector. As such, it shares +all vector characteristics and requirements, and differs only in the way the +original sequence content is specified.

+
+
+

Header

+ ++++ + + + + + + + + + + + + + +
Sequence formHeader
Variadic#include <boost/mpl/vector_c.hpp>
Numbered#include <boost/mpl/vector/vectorn_c.hpp>
+
+ +
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in vector.

+ + ++++ + + + + + + + + + + + + + + + + +
ExpressionSemantics
+vector_c<T,c1,c2,... cn>
+vectorn_c<T,c1,c2,... cn>
+
+
A vector of integral constant wrappers +integral_c<T,c1>, +integral_c<T,c2>, ... +integral_c<T,cn>; +see Integral Sequence Wrapper.
+vector_c<T,c1,c2,... cn>::type
+vectorn_c<T,c1,c2,... cn>::type
+
+
Identical to vectorn< +integral_c<T,c1>, +integral_c<T,c2>, ... +integral_c<T,cn> >; +see Integral Sequence Wrapper.
+vector_c<T,c1,c2,... cn>::value_type
+vectorn_c<T,c1,c2,... cn>::value_type
+
+
Identical to T; see +Integral Sequence Wrapper.
+
+
+

Example

+
+typedef vector_c<int,1,2,3,5,7,12,19,31> fibonacci;
+typedef push_back<fibonacci,int_<50> >::type fibonacci2;
+
+BOOST_MPL_ASSERT_RELATION( front<fibonacci2>::type::value, ==, 1 );
+BOOST_MPL_ASSERT_RELATION( back<fibonacci2>::type::value, ==, 50 );
+
+
+ +
+ + + + + diff --git a/doc/refmanual/vector.html b/doc/refmanual/vector.html new file mode 100644 index 0000000..57cf099 --- /dev/null +++ b/doc/refmanual/vector.html @@ -0,0 +1,183 @@ + + + + + + +The MPL Reference Manual: vector + + + + + +
Front Page / Sequences / Classes / vector
+
+

vector

+
+

Description

+

vector is a variadic, random access, extensible sequence of types that +supports constant-time insertion and removal of elements at both ends, and +linear-time insertion and removal of elements in the middle. On compilers that +support the typeof extension, vector is the simplest and in many cases the +most efficient sequence.

+
+ + +
+

Expression semantics

+

In the following table, v is an instance of vector, pos and last are iterators +into v, r is a Forward Sequence, n is an Integral Constant, and x and +t1,t2,... tn are arbitrary types.

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionSemantics
+vector<t1,t2,... tn>
+vectorn<t1,t2,... tn>
+
+
vector of elements t1,t2,... tn; see +Variadic Sequence.
+vector<t1,t2,... tn>::type
+vectorn<t1,t2,... tn>::type
+
+
Identical to vectorn<t1,t2,... tn>; +see Variadic Sequence.
begin<v>::typeAn iterator pointing to the beginning of v; +see Random Access Sequence.
end<v>::typeAn iterator pointing to the end of v; +see Random Access Sequence.
size<v>::typeThe size of v; see Random Access Sequence.
empty<v>::typeA boolean Integral Constant c such that +c::value == true if and only if the sequence is empty; +see Random Access Sequence.
front<v>::typeThe first element in v; see +Random Access Sequence.
back<v>::typeThe last element in v; see +Random Access Sequence.
at<v,n>::typeThe nth element from the beginning of v; see +Random Access Sequence.
insert<v,pos,x>::typeA new vector of following elements: +[begin<v>::type, pos), x, +[pos, end<v>::type); see Extensible Sequence.
insert_range<v,pos,r>::typeA new vector of following elements: +[begin<v>::type, pos), +[begin<r>::type, end<r>::type) +[pos, end<v>::type); see Extensible Sequence.
erase<v,pos>::typeA new vector of following elements: +[begin<v>::type, pos), +[next<pos>::type, end<v>::type); see +Extensible Sequence.
erase<v,pos,last>::typeA new vector of following elements: +[begin<v>::type, pos), +[last, end<v>::type); see Extensible Sequence.
clear<v>::typeAn empty vector; see Extensible Sequence.
push_back<v,x>::typeA new vector of following elements: +[begin<v>::type, end<v>::type), x; +see Back Extensible Sequence.
pop_back<v>::typeA new vector of following elements: +[begin<v>::type, prior< end<v>::type >::type); +see Back Extensible Sequence.
push_front<v,x>::typeA new vector of following elements: +[begin<v>::type, end<v>::type), x; see Front Extensible Sequence.
pop_front<v>::typeA new vector of following elements: +[next< begin<v>::type >::type, end<v>::type); +see Front Extensible Sequence.
+
+
+

Example

+
+typedef vector<float,double,long double> floats;
+typedef push_back<floats,int>::type types;
+
+BOOST_MPL_ASSERT(( is_same< at_c<types,3>::type, int > ));
+
+
+ +
+ + + + + diff --git a/doc/refmanual/views.html b/doc/refmanual/views.html new file mode 100644 index 0000000..414e754 --- /dev/null +++ b/doc/refmanual/views.html @@ -0,0 +1,40 @@ + + + + + + +The MPL Reference Manual: Views + + + + + +
Front Page / Sequences / Views
+
+

Views

+

A view is a sequence adaptor delivering an altered presentation of +one or more underlying sequences. Views are lazy, meaning that their +elements are only computed on demand. Similarly to the short-circuit +logical operations and eval_if, views make it possible to avoid +premature errors and inefficiencies from computations whose results +will never be used. When approached with views in mind, many +algorithmic problems can be solved in a simpler, more conceptually +precise, more expressive way.

+ + + +
+ + + + + diff --git a/doc/refmanual/void.html b/doc/refmanual/void.html new file mode 100644 index 0000000..7604ce1 --- /dev/null +++ b/doc/refmanual/void.html @@ -0,0 +1,51 @@ + + + + + + +The MPL Reference Manual: void_ + + + + + +
Front Page / Data Types / Miscellaneous / void_
+
+

void_

+
+

Synopsis

+
+struct void_
+{
+    typedef void_ type;
+};
+
+template< typename T > struct is_void;
+
+
+
+

Description

+

void_ is a generic type placeholder representing "nothing".

+ +
+
+

Header

+
+#include <boost/mpl/void.hpp>
+
+
+ +
+ + + + + diff --git a/doc/refmanual/zip-view.html b/doc/refmanual/zip-view.html new file mode 100644 index 0000000..036b982 --- /dev/null +++ b/doc/refmanual/zip-view.html @@ -0,0 +1,137 @@ + + + + + + +The MPL Reference Manual: zip_view + + + + + +
Front Page / Sequences / Views / zip_view
+
+

zip_view

+
+

Synopsis

+
+template<
+      typename Sequences
+    >
+struct zip_view
+{
+    // unspecified
+    // ...
+};
+
+
+
+

Description

+

Provides a "zipped" view onto several sequences; that is, represents several +sequences as a single sequence of elements each of which, in turn, +is a sequence of the corresponding Sequences' elements.

+
+
+

Header

+
+#include <boost/mpl/zip_view.hpp>
+
+
+ +
+

Parameters

+ +++++ + + + + + + + + + + + + +
ParameterRequirementDescription
SequencesA Forward Sequence of +Forward SequencesSequences to be "zipped".
+
+
+

Expression semantics

+

The semantics of an expression are defined only +where they differ from, or are not defined in Forward Sequence.

+

In the following table, v is an instance of zip_view, seq a Forward Sequence of n +Forward Sequences.

+ ++++ + + + + + + + + + + + + + +
ExpressionSemantics
+zip_view<seq>
+zip_view<seq>::type
+
+
A lazy Forward Sequence v such that for each i +in [begin<v>::type, end<v>::type) and for each j in +[begin<seq>::type, end<seq>::type) +deref<i>::type is identical to +transform< deref<j>::type, deref<_1> >::type.
size<v>::type

The size of v; size<v>::value is equal to

+
+deref< min_element<
+      transform_view< seq, size<_1> >
+    >::type >::type::value;
+
+

linear complexity; see Forward Sequence.

+
+
+
+

Example

+

Element-wise sum of three vectors.

+
+typedef vector_c<int,1,2,3,4,5> v1;
+typedef vector_c<int,5,4,3,2,1> v2;
+typedef vector_c<int,1,1,1,1,1> v3;
+
+typedef transform_view<
+      zip_view< vector<v1,v2,v3> >
+    , unpack_args< plus<_1,_2,_3> >
+    > sum;
+
+BOOST_MPL_ASSERT(( equal< sum, vector_c<int,7,7,7,7,7> > ));
+
+
+ +
+ + + + + diff --git a/doc/src/acknw.sgml b/doc/src/acknw.sgml deleted file mode 100644 index df621e4..0000000 --- a/doc/src/acknw.sgml +++ /dev/null @@ -1,18 +0,0 @@ - -
-Acknowledgements</> - -<para> -Following is a list of people who in one or another way contributed to the library development. The list is work in progress! -</> - -<para> -David Abrahams, Emily Winch, Eric Friedman, Vesa Karvonen, Peter Dimov, Mat Marcus, Fernando Cacciola, Paul Mensonides, David B. Held, John Bandela, Arnaldur Gylfason, Hamish Mackenzie. -</> - -<formalpara> -<title>Copyright on this document</> -<para>Copyright © 2002 Aleksey Gurtovoy, David Abrahams and Emily Winch.</> -</> - -</section> diff --git a/doc/src/apply_if.sgml b/doc/src/apply_if.sgml deleted file mode 100644 index 0f8bf91..0000000 --- a/doc/src/apply_if.sgml +++ /dev/null @@ -1,130 +0,0 @@ -<!-- ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| section --> -<section id="applyif"> -<title>apply_if</> - -<para> -In run-time &Cxx;, it is guaranteed that when we reach an <literal>if</> statement, only one branch will be executed. Executing the branch for which the result is not required would be unnecessary and inefficient. More importantly, frequently the non-required branch is invalid, and executing it would cause an error. For instance, the following code would be badly broken if both branches of the statement were evaluated: -</> - -<programlisting> -<![CDATA[ -void fun(giraffe* g) -{ - if (g) - cout << g->name(); - else - cout << "no giraffe"; -} -]]> -</> - -<para> -In compile-time world, things are different. Which parameters to <literal>if_</> template are instantiated is determined by the form of each template parameter and the corresponding language rules (<citation><xref linkend="ref.ISO98"></>, section 14.7.1), not by the value of the compile-time expression being switched on. That means that if, in attempt to process a particular <literal>if_</> construct, the compiler determines that one of its <quote>branch</> template parameters is ill-formed, it will issue a diagnostics even if the value of compile-time expression would lead to <quote>choosing</> the other, valid parameter type. -</> - -<para> -To clarify what we just said, here is a broken first attempt at writing a <literal>pointed_type</> metafunction, that when instantiated for a <literal>T</> that is either a plain pointer or a smart pointer, <quote>returns</> the pointed type: -</> - -<programlisting> -<![CDATA[ -template< typename T > -struct pointed_type -{ - typedef typename mpl::if_< - boost::is_pointer<T> - , typename boost::remove_pointer<T>::type - , typename T::element_type // #1 - >::type type; -}; - -typedef pointed_type< std::auto_ptr<int> >::type int_ptr; // ok -typedef pointed_type<char*>::type char_ptr; // error in line #1! -]]> -</> - -<para> -If we try to compile the above, we will get something like this: -</> - -<programlisting> -Error: name followed by "::" must be a class or namespace name -</> - -<para> -because the expression <literal>typename T::element_type</> is not valid in case of <literal>T == char*</>. -</> - -<para> -Here's what we need to do to make <literal>pointed_type</> work for plain pointers: - -<footnote><para> -It would be easy to implement <literal>pointed_type</> using partial specialization to distinguish the case where <literal>T</> is a pointer. <literal>if_</> is used here to avoid creating a complicated example. -</></> - -instead of instantiating our two potential results before passing them to <literal>if_</>, we need to write metafunctions that can be used to instantiate the results; then we can use <literal>if_</> to choose a metafunction, and only then should we use that function to get the result. -</> - -<para> -<literal>boost::remove_pointer</> already is a metafunction. We just need to write an auxiliary function to return the <literal>element_type</> of a pointer type: -</> - -<programlisting> -<![CDATA[ -namespace aux { -template< typename T > -struct element_type -{ - typedef typename T::element_type type; -}; -} -]]> -</> - -<para> -Now we can select the metafunction to call based on the result of <literal>boost::is_pointer</>, and then <emphasis>apply</> it to form the result: -</> - -<programlisting> -<![CDATA[ -template< typename T > -struct pointed_type -{ - private: - // pick a metafunction - typedef typename mpl::if_< - boost::is_pointer<T> - , boost::remove_pointer<T> - , aux::element_type<T> - >::type func_; // #1 - - public: - // apply the metafunction - typedef typename func_::type type; -}; -]]> -</> - -<para> -The key knowledge that makes the above viable is that in line #1 the compiler is <emphasis>guaranteed</> not to instantiate <literal>boost::remove_pointer<T></> and <literal>aux::element_type<T></> templates, - even although they are passed as actual arguments to the <literal>if_</>. -</> - -<para> -The described technique is so common in template metaprograms, that it makes sense to facilitate the selection of the nested <literal>type</> member by introducing a high level equivalent to <literal>if_</> that will do <literal>func_::type</> operation as a part of its invocation. The MPL provides such a template - it's called <literal>apply_if</>. Using it, we can re-write the above code as simply as: -</> - -<programlisting> -[<![CDATA[ -template< typename T > -struct pointed_type -{ - typedef typename mpl::apply_if< - boost::is_pointer<T> - , boost::remove_pointer<T> - , aux::element_type<T> - >::type type; -}; -]]> -</> - -</section> diff --git a/doc/src/apply_if2.sgml b/doc/src/apply_if2.sgml deleted file mode 100644 index 0ee49a2..0000000 --- a/doc/src/apply_if2.sgml +++ /dev/null @@ -1,55 +0,0 @@ -<!-- ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| section --> -<section id="applyif2"> -<title>apply_if, part 2</> - -<para> -Besides solving the <quote>making the code compile</> problem, the <literal>apply_if</> technique we've just learned can be also used to improve metaprogram efficiency. -</> - -<para> -Suppose we want to define a high-level wrapper around <literal>boost::remove_pointer</> traits template, which will strip the pointer qualification conditionally. We will call it <literal>remove_pointer_if</>: -</> - -<programlisting> -<![CDATA[ -template< - typename Condition - , typename T - > -struct remove_pointer_if -{ - typedef typename mpl::if_< - Condition - , typename boost::remove_pointer<T>::type - , T - >::type type; -}; -]]> -</> - -<para> -The above works the first time, but it's not the most optimal implementation. Similar to our previous examples, <literal>boost::remove_pointer<T></> gets instantiated even if its result is never used. In the metaprogramming world compilation time is an important resource <citation><xref linkend="ref.Abr01"></>, and it is wasted by unnecessary template instantiations. -</> - -<para> -Let's see what we need to substitute <literal>if_</> by <literal>apply_if</> here. We already have one metafunction to pass to <literal>apply_if</> - <literal>boost::remove_pointer<T></>, but we need a second one, - let's call it <literal>f</>, - such as <literal>f<T>::type == T</>. We could write this one ourselves, but fortunately &MPL; already provides us with a template that matches this exact definition - it's called <literal>identity</>. Applying this knowledge, we get: -</> - -<programlisting> -<![CDATA[ -template< - typename Condition - , typename T - > -struct remove_pointer_if -{ - typedef typename mpl::apply_if< - Condition - , boost::remove_pointer<T> - , mpl::identity<T> - >::type type; -}; -]]> -</> - -</section> diff --git a/doc/src/articleinfo.sgml b/doc/src/articleinfo.sgml deleted file mode 100644 index 9ed58c4..0000000 --- a/doc/src/articleinfo.sgml +++ /dev/null @@ -1,2 +0,0 @@ -<articleinfo> -</articleinfo> diff --git a/doc/src/bibliography.sgml b/doc/src/bibliography.sgml deleted file mode 100644 index 3268196..0000000 --- a/doc/src/bibliography.sgml +++ /dev/null @@ -1,69 +0,0 @@ -<bibliography id="bibliography"> -<title>Bibliography</> - -<biblioentry id="ref.Abr01"> - <abbrev>Abr01</> - <authorgroup> - <author><firstname>David</><surname>Abrahams</></> - <author><firstname>Carlos Pinto</><surname>Coelho</></> - </> - <title><ulink url="http://users.rcn.com/abrahams/instantiation_speed/index.html">Effects of Metaprogramming Style on Compilation Time</></> - <date>2001</> -</biblioentry> - -<biblioentry id="ref.Ale00"> - <abbrev>Ale00</> - <author><firstname>Andrei</><surname>Alexandrescu</></> - <title><ulink url="http://www.cuj.com/experts/1810/alexandr.htm">On Conversions between Types and Values</></> - <publishername>C/C++ Users Journal</> - <date>October 2000</> -</biblioentry> - -<biblioentry id="ref.BBL"> - <abbrev>BBL</> - <title>Boost Bind library</> - <bibliomisc><ulink url="http://www.boost.org/libs/bind/bind.html"></></> -</biblioentry> - -<biblioentry id="ref.ISO98"> - <abbrev>ISO98</> - <title>ISO/IEC 14882:1998(E), Programming languages — C++</> - <orgname>ISO/IEC</> - <date>1998</> -</biblioentry> - -<biblioentry id="ref.PRE"> - <abbrev>PRE</> - <author><firstname>Vesa</><surname>Karvonen</></> - <title>Boost Preprocessor Metaprogramming library</> - <bibliomisc><ulink url="http://www.boost.org/libs/preprocessor/doc/"></></> -</biblioentry> - -<biblioentry id="ref.TTL"> - <abbrev>TTL</> - <title>Boost Type Traits library</> - <bibliomisc><ulink url="http://www.boost.org/libs/type_traits/"></></> -</biblioentry> - -<biblioentry id="ref.SAL"> - <abbrev>SAL</> - <title>Boost Static Assert library</> - <bibliomisc><ulink url="http://www.boost.org/libs/static_assert/static_assert.htm"></></> -</biblioentry> - -<biblioentry id="ref.Vel95a"> - <abbrev>Vel95a</> - <author><firstname>Todd</><surname>Veldhuizen</></> - <title><ulink url="http://osl.iu.edu/~tveldhui/papers/Template-Metaprograms/meta-art.html">Using C++ template metaprograms</></> - <biblioset relation='journal'> - <title>C++ Report</> - <publishername>SIGS Publications Inc.</> - <issn>1040-6042</> - </> - <volumenum>7</> - <issuenum>4</> - <pagenums>36-43</> - <date>May 1995</> -</biblioentry> - -</bibliography> diff --git a/doc/src/body.sgml b/doc/src/body.sgml deleted file mode 100644 index 672b57d..0000000 --- a/doc/src/body.sgml +++ /dev/null @@ -1,37 +0,0 @@ -<!doctype article public "-//OASIS//DTD DocBook V4.1//EN" -[ -<!-- abbreviations --> -<!entity Boost "<literal>Boost</>"> -<!entity Cxx "C++"> -<!entity C "C"> -<!entity MPL "MPL"> -<!entity BMPL "Boost Metaprogramming Library"> -<!entity mdat "metadata"> -<!entity mping "metaprogramming"> -<!entity mfn "metafunction"> -<!entity unspec "/*unspecified*/"> - -<!-- physical entities --> -<!entity articleinfo SYSTEM "articleinfo.sgml"> -<!entity preface SYSTEM "preface.sgml"> -<!entity tutorial SYSTEM "tutorial.sgml"> -<!entity metafunctions SYSTEM "metafunctions.sgml"> -<!entity if SYSTEM "if.sgml"> -<!entity applyif SYSTEM "apply_if.sgml"> -<!entity applyif2 SYSTEM "apply_if2.sgml"> -<!entity technical SYSTEM "technical.sgml"> -<!entity acknw SYSTEM "acknw.sgml"> -<!entity bibliography SYSTEM "bibliography.sgml"> -]> - -<article> -<title>The Boost &MPL; Library</> - -&articleinfo; -&preface; -&tutorial; -&technical; -&acknw; -&bibliography; - -</article> diff --git a/doc/src/howtos.sgml b/doc/src/howtos.sgml deleted file mode 100644 index b15df69..0000000 --- a/doc/src/howtos.sgml +++ /dev/null @@ -1,58 +0,0 @@ -<!-- ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| section --> -<section id="howtos"> -<title>How-to's</> - -<!-- ||||||||||||||||||||||||||||| subsection --> -<section id="howtos.search"> -<title>How to find something in a sequence?</> - -<para> -If you just want to make an enquiry if a sequence contains a type with certain properties, you can do it like that: -</> - -<programlisting> -<![CDATA[ -typedef mpl::list5<> types; -typedef mpl::contains<types,int>::type res; // res::value == true -]]> -</> - -<para> -A predicate version of <literal>contains</> algorithm is spelled <literal>any</>: -</> - -<programlisting> -<![CDATA[ -// find if any type in 'types' is derived from 'my' -typedef mpl::any<types, mpl::is_convertible<_1,my> >::type res; -]]> -</> - -<para> -Now, if you really want to find type in a sequence - that is, to obtain an iterator on its position, when the should-be-known-from-STL <literal>find</> and <literal>find_if</> algorithms are most probably exactly what you need: -</> - -<programlisting> -<![CDATA[ -// find if any type in 'types' is derived from 'my' -typedef mpl::find<types, int >::type iterator; -typedef mpl::find_if<types, mpl::is_convertible<_1,my> >::type iterator; -]]> -</> - -<para> -Unless, of course, the sequence is sorted. If it is, then the other known names come into the play - <literal>lower_bound</>, <literal>upper_bound</>, or <literal>binary_search</>: -</> - -<programlisting> -<![CDATA[ -// find if any type in 'types' is derived from 'my' -typedef mpl::lower_bound<types, mpl::int_c<5>, mpl::less<_1,_2> >::type iterator; -typedef mpl::upper_bound<types, mpl::int_c<5>, mpl::less<_1,_2> >::type iterator; -typedef mpl::binary_search<types, mpl::int_c<5>, mpl::less<_1,_2> >::type iterator; -]]> -</> - -</section> - -</section> diff --git a/doc/src/if.sgml b/doc/src/if.sgml deleted file mode 100644 index 8f68685..0000000 --- a/doc/src/if.sgml +++ /dev/null @@ -1,66 +0,0 @@ -<!-- ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| section --> -<section id="if"> -<title>Compile-time if</> - -<para> -The most interesting template metaprograms often contain a lot of decision-making code. Some of conditional decisions/behavior can be handled directly by (partial) class template specialization or function overloading <citation><xref linkend="ref.Vel95a"></>, <citation><xref linkend="ref.Ale00"></>, but in general there is a need for a standalone library primitive that would allow one to choose between two types basing on a compile-time expression. In <literal>boost::mpl</> such primitive is called <literal>if_</>: -</> - -<programlisting> -<![CDATA[ -template< typename T > -struct heap_holder -{ - // ... - private: - boost::scoped_ptr<T> m_object; -}; - -template< typename T > -struct stack_holder -{ - // ... - private: - T m_object; -}; - -template< typename T > -struct can_be_on_stack - : mpl::bool_c< (sizeof(T) <= sizeof(double)) > -{ -}; - -// use 'if_' to choose where to store 'T' member -template< typename T > -struct lightweight - : private mpl::if_< - can_be_on_stack<T> - , stack_holder<T> - , heap_holder<T> - >::type -{ - // ... -}; -]]> -</> - -<para> -Note that the first template parameter of the <literal>if_</> template is a type that should be a model of Integral Constant concept. The library also provides a less generic but sometimes more convenient form that accepts a condition in form of non-type <literal>bool</> template parameter: -</> - -<programlisting> -<![CDATA[ -template< typename T > -struct lightweight - : private mpl::if_c< - (sizeof(T) <= sizeof(double)) - , stack_holder<T> - , heap_holder<T> - >::type -{ - // ... -}; -]]> -</> - -</section> diff --git a/doc/src/lambda.sgml b/doc/src/lambda.sgml deleted file mode 100644 index 45846cd..0000000 --- a/doc/src/lambda.sgml +++ /dev/null @@ -1,30 +0,0 @@ -<!-- ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| section --> -<section id="lambda"> -<title>Lambda facility</> - -<para> -<firstterm>Lambda expressions</> is a way of inline meta-function composition. - -building more complex, more interesting functions from the existing ones. The simplest case of function composition is an operation of taking the result from one function (<literal>g</>) and using that as the argument to another function (<literal>f</>) - <literal>f(g(x))</>. [Talk about run-time &Cxx; facilities to do function composition in &Cxx; - SGI STL <literal>compose1</>/<literal>compose2</>, Boost Compose library, Boost Bind library] -</> - -<para> -The library provide support for several styles of function composition. The facilities differ in portability, implementation complexity, readability, and performance characteristics. -</> - -<!-- ||||||||||||||||||||||||||||| subsection --> -<section id="bind.compose"> -<title>compose</> - -<programlisting> -<![CDATA[ -using mpl::placeholders; -typedef mpl::bind< mpl::make_f2<boost::is_same>,int,_2 > is_int; -typedef mpl::bind< add_pointer,mpl::bind<add_const,_1> > add_const_pointer; -]]> -</> - - -</section> - -</section> diff --git a/doc/src/metafunctions.sgml b/doc/src/metafunctions.sgml deleted file mode 100644 index afd7234..0000000 --- a/doc/src/metafunctions.sgml +++ /dev/null @@ -1,37 +0,0 @@ -<section id="metafunctions"> -<title>Metafunctions</> - -<para> -In &MPL;, the metaprogramming equivalent of a function is a <firstterm>class template</> containing a nested <literal>typedef</> member aptly named <quote>type</>: -</> - -<programlisting> -<![CDATA[ -// on the face of it, not very useful -template< typename T > -struct identity -{ - typedef T type; -}; - -// perhaps more useful -template< typename T > -struct result_type -{ - typedef typename T::result_type type; -}; -]]> -</> - -<para> -<quote>Invoking</> a metafunction is as simple as instantiating the class template with particular template parameters (metafunction <quote>arguments</>) and accessing the result through the nested <literal>type</> member: -</> - -<programlisting> -<![CDATA[ -typedef identity<int>::type t1; // t1 == int -typedef result_type< std::unary_function<int,bool> >::type t2; // t2 == bool -]]> -</> - -</section> diff --git a/doc/src/preface.sgml b/doc/src/preface.sgml deleted file mode 100644 index 85bb6bc..0000000 --- a/doc/src/preface.sgml +++ /dev/null @@ -1,49 +0,0 @@ -<!-- ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| section --> -<section id="preface"> -<title>Preface</> - -<para>The &MPL; library is a &Cxx; template metaprogramming framework of compile-time algorithms, sequences and metafunction classes. The two main documentation sources for the library is <quote>the MPL paper</>, and the library's reference documentation. If you haven't heard about the MPL before, we suggest you to start with the paper, and then move on to the reference documentation and the information in this document. -</> - -<itemizedlist mark="box"> - -<listitem><simpara> -A. Gurtovoy, D. Abrahams, <ulink url="./paper/html/index.html">The Boost C++ Metaprogramming Library</>, March 2002 | [<ulink url="./paper/mpl_paper.html">as single .html</>]</></listitem> - -<listitem> -<ulink url="./ref/Table_of_Content.html">Reference documentation</> - <orderedlist> - <listitem><simpara><ulink url="./ref/Sequences.html">Sequences</></></> - <listitem><simpara><ulink url="./ref/Iterators.html">Iterators</></></> - <listitem><simpara><ulink url="./ref/Algorithms.html">Algorithms</></></> - <listitem><simpara><ulink url="./ref/Metafunctions.html">Metafunctions</></></> - <listitem><simpara><ulink url="./ref/Categorized_index.html">Categorized index</></></> - </orderedlist> -</listitem> - -</itemizedlist> - -</section> - -<!-- ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| section --> -<section id="source"> -<title>Sources</> - -<para> -The latest library sources are available from: -</> - -<itemizedlist mark="box"> - <listitem><simpara>The <ulink url="http://www.boost.org/more/download.html#CVS">boost CVS</>, <literal>mpl_v2</> branch (<literal>cvs update -P -rmpl_v2 boost/mpl boost/type_traits libs/mpl</>)</></> - <listitem><simpara>From here - <ulink url="http://www.mywikinet.com/mpl/mpl_23_jul_02.zip"></></></> - -</itemizedlist> - -<para> -The library also requires the latest version of Boost Preprocessor library, that can be also obtained from <ulink url="http://www.boost.org/more/download.html#CVS">boost CVS</> or from here - <ulink url="http://www.mywikinet.com/mpl/preprocessor_19_jul_02.zip"></>. -</> - -<para>A full archive that contains the library itself + all its dependencies - and therefore can be installed over a clean <ulink url="http://boost.sourceforge.net/release/boost_1_28_0.zip">Boost 1.28 distribution</> - is available from here - <ulink url="http://www.mywikinet.com/mpl/mpl_23_jul_02_full.zip"></>. -</> - -</section> diff --git a/doc/src/sequences.sgml b/doc/src/sequences.sgml deleted file mode 100644 index 2494f2d..0000000 --- a/doc/src/sequences.sgml +++ /dev/null @@ -1,30 +0,0 @@ -<!-- ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| section --> -<section id="sequences"> -<title>Working with type sequences</> - -<para> -If we were to design a generative container library, our first attempt could be something like this: -</> - -<programlisting> -<![CDATA[ -namespace ctl { // Container Template Library - -template< - typename T - , typename Features - > -class container -{ - // ... -}; - -} // namespace ctl -]]> -</> - -<para> -Here, <literal>container</> template is a single generative interface to all the , and we would like to pass to a possibly numerous features of a container as a single type. -</> - -</section> diff --git a/doc/src/technical.sgml b/doc/src/technical.sgml deleted file mode 100644 index b50d14a..0000000 --- a/doc/src/technical.sgml +++ /dev/null @@ -1,52 +0,0 @@ -<!-- ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| section --> -<section id="technical"> -<title>Technical details</> - -<!-- ||||||||||||||||||||||||||||| subsection --> -<section id="details.headers"> -<title>Physical structure</> - -<para> -The library provides you with a fine-grained header structure with one header per public component (class/function template), with the header named after the component; for example, <literal>boost::mpl::apply<></> template is defined in the header <literal>boost/mpl/apply.hpp</>. This scheme both ensures that you don't pay for what you don't use in terms of compilation time/header dependencies, and frees you from memorizing/looking up header/component correspondence. Several composite headers for the entities that are likely to be used together (e.g. logical operations - <literal>logical_or</>, <literal>logical_and</>, etc.) are also provided. It allows one to avoid the burden of spelling many <literal>#include</> directives in programs that make an intensive use of the library facilities. - -<footnote id="note.headers"><para>The Boost Preprocessor library <citation><xref linkend="ref.PRE"></> exposes a very similar physical organization; in fact, the libraries even share the common subdirectory naming (<literal>mpl/arithmetic</> <-> <literal>preprocessor/arithmetic</>, <literal>mpl/comparison</> <-> <literal>preprocessor/comparison</>, etc.).</></> - -</> - -</section> - -<!-- ||||||||||||||||||||||||||||| subsection --> -<section id="details.depend"> -<title>Dependencies</> - -<para> -Besides <literal>boost/config.hpp</> header, the MPL heavily depends on two other Boost libraries - the Boost Preprocessor library <citation><xref linkend="ref.PRE"></>, and the Type Traits library <citation><xref linkend="ref.TTL"></>. These dependencies are essential and cannot be eliminated. In addition to those, the <literal>boost/mpl/assert.hpp</> header depends on Boost Static Assert library <citation><xref linkend="ref.SAL"></>. The library tests and examples may depend on some additional Boost libraries, e.g. Boost Bind <citation><xref linkend="ref.BBL"></>; you don't have to have those unless you are interested in actually compiling the tests/examples (probably you are, though). -</> - -</section> - -<!-- ||||||||||||||||||||||||||||| subsection --> -<section id="details.portability"> -<title>Portability</> - -<para> -Below is the list of compilers the library has been tested with: -</> - -<itemizedlist mark="box"> -<listitem><simpara>Microsoft Visual C++ 6.0, SP 5</></> -<listitem><simpara>Microsoft Visual C++ .NET (7.0)</></> -<listitem><simpara>Metrowerks CodeWariror 7.2/8.1</></> -<listitem><simpara>Intel C++ Compiler 5.0, 6.0</></> -<listitem><simpara>GCC 2.95.3-5</></> -<listitem><simpara>GCC 3.1</></> -<listitem><simpara>Comeau C/C++ 4.2.45/4.3.0</></> -<listitem><simpara>Borland C++ 5.5.1</></> -</> - -<para>An incomplete matrix of recent test compilation results is available from here - <ulink url="http://www.mywikinet.com/mpl/log.html"></>. -</> - -</section> - -</section> diff --git a/doc/src/tutorial.sgml b/doc/src/tutorial.sgml deleted file mode 100644 index be77b98..0000000 --- a/doc/src/tutorial.sgml +++ /dev/null @@ -1,29 +0,0 @@ -<!-- ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| section --> -<section id="tutorial"> -<title>Mini-tutorial</> - -<!-- ||||||||||||||||||||||||||||| subsection --> -<section id="tutorial.conventions"> -<title>Conventions used</> - -<para> -The examples used through this tutorial use fully qualified names, e.g. <literal>std::vector</> instead of plain <literal>vector</>. Any unqualified name refers to a local entity defined in the example itself. The names from <literal>boost::mpl</> namespace are referred to using <literal>mpl</> namespace alias (e.g. <literal>mpl::apply</> instead of <literal>boost::mpl::apply</>), as if the following namespace alias definition were in effect: -</> - -<programlisting> -<![CDATA[ -namespace mpl = boost::mpl; -]]> -</> - -<para>Note that the library offers a special header, <literal>boost/mpl/alias.hpp</>, including which gives you a rough equivalent of the above. Alternatively, you can always spell the namespace alias definition manually in each translation unit as needed (if you choose to use the shorter namespace notation at all). -</> - -</section> - -&metafunctions; -&if; -&applyif; -&applyif2; - -</section> \ No newline at end of file diff --git a/doc/style.css b/doc/style.css new file mode 100644 index 0000000..8dc82f7 --- /dev/null +++ b/doc/style.css @@ -0,0 +1,720 @@ +/* + +:Author: David Goodger +:Author: Aleksey Gurtovoy +:Copyright: This stylesheet has been placed in the public domain. + +*/ + + + +.first +{ + margin-top: 0; +} + +.last +{ + margin-bottom: 0; +} + + + +/* <a/> */ + + +a +{ + color: #0000cc; +} + +a:visited +{ + color: #800080; +} + +/* +sup a:link, +sup a:visited, +a.interlink:link, +a.interlink:visited +{ + color: #505050; + text-decoration: none; +} +*/ + +a.refentry +{ + text-decoration: none; +} + +a.subsection-title:link, +a.subsection-title:active, +a.subsection-title:visited, +a.subsection-title:hover +{ + color: black; + text-decoration: none; +} + +a.identifier:link, +a.identifier:active, +a.identifier:visited +{ + color: black; + text-decoration: none; +} + +a.header:link, +a.header:active, +a.header:visited +{ + color: black; + text-decoration: none; +} + + +a.identifier:hover, +a.header:hover +{ + color: #0000cc; +} + +a.toc-backref:link, +a.toc-backref:active, +a.toc-backref:visited, +a.toc-backref:hover +{ + text-decoration: none; + color: black +} + +a.ref-subsection-title +{ + text-decoration: none; + color: black; +} + + +/* <blockquote/> */ + +blockquote.epigraph +{ + margin: 2em 5em; +} + + +/* <caption/> */ + +caption +{ + font-weight: bold; +} + + +/* <body/> */ + +body +{ + background: #fffff5; +} + +body.refmanual +{ + background: #fffff5 url(refmanual/manual.png) no-repeat top right fixed; + margin-right: 25pt; +} + +/* <dd/> */ + +dd +{ + margin-bottom: 0.5em; +} + + + +/* <div/> */ + +div.abstract +{ + margin: 2em 5em; +} + +div.dedication +{ + margin: 2em 5em; + text-align: center; + font-style: italic; +} + + +div.figure +{ + margin-left: 2em; +} + +div.sidebar +{ + border: solid 1px black; + padding: 1em; + background-color: #ffffee; + width: 40%; + float: right; + clear: right; +} + +div.compound +{ + margin-top: 15pt; +} + +div.document, +div.section +{ + margin-left: 3pt; + margin-right: 3pt; +} + + body.refmanual +div.section +{ + margin-left: 1pt; + margin-right: 0pt; +} + + +div.system-messages +{ + margin: 5em; +} + +div.system-message +{ + border: medium outset; + padding: 1em; +} + +div.topic +{ + margin: 2em; +} + + +div.attention, +div.caution, +div.danger, +div.error, +div.hint, +div.important, +div.note, +div.tip, +div.warning, +div.admonition +{ + margin: 2em; + border: solid 1px black; + padding: 1em; +} + +div.header-separator, +div.footer-separator +{ + border-top: solid 1px #a09a8b; + border-bottom: solid 1px #e4e2de; +} + + + +/* <dt/> */ + +dt +{ + font-weight: bold +} + + + +/* <h/> */ + + +h1.title +{ + text-align: center; + vertical-align: text-bottom; + + padding-top: 15pt; + padding-bottom: 5pt; + padding-right: 277px; /* logo width */ + padding-left: 277px; /* logo width */ +} + +h2.subtitle +{ + text-align: center; +} + + div.system-messages +h1 +{ + color: red; +} + + div.section +h1 +{ + margin-top: 7pt; + margin-bottom: 10pt; +} + + body.refmanual + div.section +h3 +{ + margin-bottom: 0pt; + padding-bottom: 0pt; + +/* + padding-left: 1pt; + border-style: none none solid none; + border-width: 2px; + border-color: #f0a0a0; +*/ +} + + + +/* <hr/> */ + +hr.header-separator +{ + width: 100%; + display: none; +/* margin-top: 1pt;*/ +} + +hr.footer-separator +{ + width: 100%; +/* margin-bottom: 1pt;*/ +} + + + +/* <img/> */ + +img +{ + border: 0; +} + +img.right-aligned +{ + padding-left: 5pt; + padding-bottom: 5pt; +} + + +/* <ol/> */ + +ol.simple +{ + margin-bottom: 1em; +} + +ol.arabic +{ + list-style: decimal; +} + +ol.loweralpha +{ + list-style: lower-alpha; +} + +ol.upperalpha +{ + list-style: upper-alpha; +} + +ol.lowerroman +{ + list-style: lower-roman; +} + +ol.upperroman +{ + list-style: upper-roman; +} + + + +/* <p/> */ + +p +{ + margin-top: 7pt; + padding-top: 0pt; +} + +p.attribution +{ + text-align: right; + margin-left: 50%; +} + +p.caption +{ + font-style: italic; +} + +p.credits +{ + font-style: italic; + font-size: smaller; +} + +p.label +{ + white-space: nowrap; +} + +p.rubric +{ + font-weight: bold; + font-size: larger; + color: maroon; + text-align: center; +} + +p.topic-title +{ + font-weight: bold; + margin-top: 5pt; +} + +p.sidebar-title +{ + font-family: sans-serif; + font-weight: bold; +} + +p.sidebar-subtitle +{ + font-family: sans-serif; + font-weight: bold; +} + + div.abstract +p.topic-title +{ + font-weight: bold; + text-align: center; +} + + div.dedication +p.topic-title +{ + font-weight: bold; + font-style: normal; +} + + div.system-message +p.system-message-title +{ + color: red; + font-weight: bold; +} + + div.attention +p.admonition-title, + div.caution +p.admonition-title, + div.danger +p.admonition-title, + div.error +p.admonition-title, + div.warning +p.admonition-title +{ + color: red; + font-weight: bold; + font-family: sans-serif; +} + + div.hint +p.admonition-title, + div.important +p.admonition-title, + div.note +p.admonition-title, + div.tip +p.admonition-title, + div.admonition +p.admonition-title +{ + font-weight: bold; + font-family: sans-serif; +} + + td +p +{ + margin-top: 5pt; + margin-bottom: 5pt; +} + +/* <pre/> */ + +pre.address +{ + margin-bottom: 0; + margin-top: 0; + font-family: serif; + font-size: 100%; +} + +pre.line-block +{ + font-family: serif; + font-size: 100%; +} + + +pre.doctest-block +{ + margin-left: 2em; + margin-right: 2em; + background-color: #eeeeee; +} + +pre.literal-block +{ + border-style: none none none solid; + border-width: 1px; + border-color: black; + padding-top: 2pt; + padding-bottom: 2pt; + padding-left: 1em; + padding-right: 1em; + margin-top: 10pt; + margin-left: 0pt; +/* background-color: #f7f7f7;*/ + background-color: #f5f5f5; +} + + td +pre.literal-block +{ + border-style: none; + margin-top: 0pt; + padding-top: 0pt; + margin-bottom: 0pt; + padding-bottom: 0pt; + padding-left: 1pt; +} + +pre.literal-block +{ + margin-bottom: 1pt; +} + + + +/* <table/> */ + +table +{ + margin-top: 0.5em; + margin-bottom: 0.5em; +} + +table.docinfo +{ + border: solid 0; + margin: 2em 4em; +} + +table.field-list +{ + border: solid 0; + margin-left: 1pt; +} + + +table.citation +{ + border: solid 0; + border-left: solid thin gray; +} + +table.footnote +{ + border: solid 0; + border-left: solid thin black; +} + +table.header, +table.footer +{ + border: solid 0; + width: 100%; + margin: 0pt; + padding: 0pt; +} + + +table.table +{ + border: solid 1px black; + border-collapse: collapse; + margin-bottom: 10pt; +} + + + +/* <td/> / <th/> */ + + table.table +td, + table.table +th +{ + border: solid 1px black; + vertical-align: top; +} + + table.table +th +{ + padding-left: 5pt; + padding-right: 5pt; +} + + table.table +td +{ + padding-left: 5pt; + padding-right: 5pt; + padding-top: 1pt; + padding-bottom: 1pt; +} + + +td.header-group +{ + padding: 0pt; + padding-bottom: 2pt; + margin: 0pt; + vertical-align: top; +} + +td.navigation-bar +{ + text-align: left; + white-space: nowrap; + padding-right: 0.5em; +} + +td.page-location +{ + text-align: right; +} + +th.docinfo-name, +th.field-name +{ + font-weight: bold; + text-align: left; + white-space: nowrap; +} + +td.label +{ + padding-left: 5pt; + padding-right: 10pt; +} + + +/* <tr/> */ + +tr.header, +tr.footer +{ + padding: 0pt; + margin: 0pt; +} + + + +/* <tt/> */ + +tt.literal +{ + background-color: #f5f5f5; +} + + h1 +tt, + h2 +tt, + h3 +tt, + h4 +tt, + h5 +tt, + h6 +tt +{ + font-size: 100%; +} + + +/* <span/> */ + +span.classifier +{ + font-family: sans-serif; + font-style: oblique; +} + +span.classifier-delimiter +{ + font-family: sans-serif; + font-weight: bold; +} + +span.interpreted +{ + font-family: sans-serif; +} + +span.option +{ + white-space: nowrap; +} + +span.option-argument +{ + font-style: italic; +} + +span.pre +{ + white-space: pre; +} + +span.problematic +{ + color: red; +} + + +/* <ul/> */ + +ul.toc +{ + list-style-type: circle; +} diff --git a/doc/tidy_attr.py b/doc/tidy_attr.py deleted file mode 100644 index d5f3de8..0000000 --- a/doc/tidy_attr.py +++ /dev/null @@ -1,28 +0,0 @@ -import re -import sys -import os -import string - -def tidy_attr(attr_value): - return string.lower(attr_value.group()) - -def tidy(file): - lines = open(file, 'r').readlines() - regex = re.compile(r'[name|class]="([^"]*)"') - xsltproc_patch = re.compile(r'(\|\|\|)') - for i in range(len(lines)): - lines[i] = regex.sub(tidy_attr,lines[i]) - lines[i] = xsltproc_patch.sub(' ',lines[i]) - - open(file, 'w') \ - .writelines(lines) - -def main(): - if len(sys.argv) < 2: - print '\tusage: %s <html document>' % sys.argv[0] - return -1 - - tidy(sys.argv[1]) - print 'done!' - -main() diff --git a/doc/tidy_config b/doc/tidy_config deleted file mode 100644 index 7bdc71d..0000000 --- a/doc/tidy_config +++ /dev/null @@ -1,7 +0,0 @@ -doctype: loose -tidy-mark: no -wrap: 0 -wrap-attributes: no -enclose-text: yes -drop-empty-paras: no -quiet: yes diff --git a/doc/tutorial/acknowledgements.html b/doc/tutorial/acknowledgements.html new file mode 100644 index 0000000..64950c6 --- /dev/null +++ b/doc/tutorial/acknowledgements.html @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> +<meta name="generator" content="Docutils 0.3.6: http://docutils.sourceforge.net/" /> +<title>THE BOOST MPL LIBRARY: Acknowledgements + + + + + +
Front Page / Acknowledgements
+
+

Acknowledgements

+

Many, many people in one or another way contributed to the library development. The +list below is known to be incomplete and needs updating! We sincerely promise to +fix it in the near feature.

+

For bug reports, patches, suggestions and insightful discussions, our thanks go to:

+
    +
  • John Bandela
  • +
  • Fernando Cacciola
  • +
  • Peter Dimov
  • +
  • Eric Friedman
  • +
  • Arnaldur Gylfason
  • +
  • David B. Held
  • +
  • Vesa Karvonen
  • +
  • Mat Marcus
  • +
  • Hamish Mackenzie
  • +
  • Paul Mensonides
  • +
  • Emily Winch
  • +
+
+ + + + + diff --git a/doc/tutorial/apply-lambda-semantics.html b/doc/tutorial/apply-lambda-semantics.html new file mode 100644 index 0000000..155671a --- /dev/null +++ b/doc/tutorial/apply-lambda-semantics.html @@ -0,0 +1,91 @@ + + + + + + +THE BOOST MPL LIBRARY: apply/lambda Semantics + + + + + +
Front Page / Changelog & History / Changes in Boost 1.32.0 Release / apply/lambda Semantics
+
+

apply/lambda Semantics

+
    +
  1. Nullary metafunction classes are now consistent with all other +metafunction classes, rather than being identical to nullary +metafunctions:

    + +++++ + + + + + + + + + + + + + + + + +

    Nullary...

    +

    Before

    +

    Now

    +

    Metafunction

    +

    f::type

    +

    f::type

    +

    Metafunction class

    +

    c::type

    +

    c::apply<>::type or +c::apply::type [7]

    +
    +

    This fixes a flaw in the metafunction class/metafunction algebra +that long has been a major source of other inconsistencies throughout +the library.

    +
  2. +
  3. The apply metafunction now automatically invokes lambda +on its first argument. For example, the following is well-formed now:

    +
    +typedef apply< plus<_1,_1>, int_<2> >::type four;
    +
    +

    apply_wrapn auxiliary metafunctions are available for rare cases +when it's crucial to eliminate the small overhead associated with lambda +expressions while still avoiding various compiler bugs known to +cause problems with +the obvious f::template apply<...>::type syntax.

    +
  4. +
  5. The lambda implementation for broken compilers has been +reworked to emulate the semantics of the full-fledged version +as closely as possible; consequently, any code out there that +was taking advantage of the semantic quirks of less complete +emulation in the previous release may stop working with the new +one.

    +
  6. +
+

To get a detailed picture of the new apply/lambda semantics, please +see the test case at +http://cvs.sourceforge.net/viewcvs.py/boost/boost/libs/mpl/test/apply.cpp?view=markup +and the corresponding sections of the MPL reference manual.

+ + + + + +
[7]The second form is available only on fully conforming compilers.
+
+ + + + + diff --git a/doc/tutorial/book_cover.png b/doc/tutorial/book_cover.png new file mode 100644 index 0000000000000000000000000000000000000000..6d587343120814263042123126da4f9d688c5a8b GIT binary patch literal 39700 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 Bq9FhP literal 0 HcmV?d00001 diff --git a/doc/tutorial/broken-integral-constant.html b/doc/tutorial/broken-integral-constant.html new file mode 100644 index 0000000..3c5dcf6 --- /dev/null +++ b/doc/tutorial/broken-integral-constant.html @@ -0,0 +1,116 @@ + + + + + + +THE BOOST MPL LIBRARY: Broken Integral Constant Expressions + + + + + +
Front Page / Technical Details / Portability / Broken Integral Constant Expressions
+
+

Broken Integral Constant Expressions

+

This is probably the most surprising of the portability issues +we're going to discuss, not least because for many C++ programmers, their everyday +experience seems to indicate no problems in this area whatsoever. After all, +integer compile-time computations along the lines of:

+
+enum flags {
+      flag1     = (1 << 0)
+    , flag2     = (1 << 1)
+    , flag3     = (1 << 2)
+    ...
+    };
+
+

are very commonplace in C++, and there is hardly a compiler out +there that cannot handle this correctly. While arithmetic by +itself is indeed rarely problematic, when you are trying to mix it +with templates on certain deficient compilers, all kinds of new +issues arise. Fortunately, as with the rest of the portability +issues we're discussing here, the problem fades into past as new +compiler versions are released. The majority of most recent +compilers of many vendors are already free from these issues.

+
+

The Problem

+

The problem is in fact multi-faceted; there are a number of +different subissues. Some are present in one set of compilers, +some are in another, and it's not uncommon for a code that works +for one compiler to break another one and vice-versa. If this +sounds like a maintenance nightmare to you, it is! If you are +interested in the specific list of issues, please refer to John +Maddock's excellent "Coding Guidelines for Integral Constant +Expressions" summary. For the purpose of our discission here, it +is sufficient to say that if your code has to work on one of the +compilers listed as problematic in this area, you can safely assume +that if you decide to fight them on a case-by-case basis, chances +are that you won't be able to maintain your sanity for very long.

+
+
+

The Symptoms

+

On the positive side, when you have an issue with integral +arithmetic, the diagnostics are almost always straightforward: +usually the error message refers you to the exact place in the code +that is causing problems, and the essence of issue is obvious from +the error's text, or it becomes obvious once you've encountered the +same error a couple of times. For instance, if we throw this +well-formed fragment at MSVC 7.1 (otherwise an excellent compiler!)

+
+void value();
+
+// compares two Integral Constants
+template< typename N1, typename N2 > struct less
+    : bool_< (N1::value < N2::value) > // line #8
+{
+};
+
+

we get:

+
+portability.cpp(8) : warning C4346: 'N2::value' : dependent name is not a type
+        prefix with 'typename' to indicate a type
+        portability.cpp(10) : see reference to class template instantiation 'less<N1,N2>' being compiled
+portability.cpp(8) : error C2143: syntax error : missing ',' before ')'
+portability.cpp(9) : error C2143: syntax error : missing ';' before '{'
+portability.cpp(10) : error C2143: syntax error : missing ';' before '}'
+portability.cpp(10) : fatal error C1004: unexpected end of file found
+
+

The errors themselves are far from being ideal, but at least we are +pointed at the correct line and even the correct part of the +line. The above basically reads as "something's wrong between the +parentheses", and that plus the "syntax error" part is usually +enough of the clue.

+
+
+

The Solution

+

Despite the fact the problems are so numerous and multi-faceted and +the workarounds are conflicting, the problems can be hidden +reliably beneath a library abstraction layer. The underlaying idea +is very simple: we can always wrap the constants in types and pass +those around. Then all that is left is to implement algebraic +metafunctions that operate on such wrappers, once, and we are home +safe.

+

If this sounds familiar to you, probably it's because you have +already took a look at the MPL and know that the approach we just +described is in fact the standard way of doing arithmetic in the +library. Although it's motivated by more general observations, +this fact comes very handy for the library users that care about +portability of their numerically-heavy metaprograms. The MPL +primitives are already there, and more importantly, they already +implement the necessary workarounds, so your numeric code just +works. In fact, if you stay within the library's type-wrapper +idioms, these particular problems never "leak" out of its +abstraction layer.

+

On a final note, there is a price of avoiding built-in arithmetics +altogether, namely decreased readability and, on some compilers, +increased compile-time overhead. Still, in majority of cases, the +benefits of type-based arithmetics overweight its small +shortcomings.

+
+
+ + + + + diff --git a/doc/tutorial/changelog-history.html b/doc/tutorial/changelog-history.html new file mode 100644 index 0000000..3f0314b --- /dev/null +++ b/doc/tutorial/changelog-history.html @@ -0,0 +1,24 @@ + + + + + + +THE BOOST MPL LIBRARY: Changelog & History + + + + + +
Front Page / Changelog & History
+ + + + + + diff --git a/doc/tutorial/changes-in-boost-1-32-0.html b/doc/tutorial/changes-in-boost-1-32-0.html new file mode 100644 index 0000000..a6fbf65 --- /dev/null +++ b/doc/tutorial/changes-in-boost-1-32-0.html @@ -0,0 +1,34 @@ + + + + + + +THE BOOST MPL LIBRARY: Changes in Boost 1.32.0 Release + + + + + +
Front Page / Changelog & History / Changes in Boost 1.32.0 Release
+
+

Changes in Boost 1.32.0 Release

+

The following summarizes major changes in the library interface and +implementation from the previous release. Note that this is not a +comprehensive list of all changes (yet).

+ + +
+ + + + + diff --git a/doc/tutorial/dependencies.html b/doc/tutorial/dependencies.html new file mode 100644 index 0000000..49ba005 --- /dev/null +++ b/doc/tutorial/dependencies.html @@ -0,0 +1,32 @@ + + + + + + +THE BOOST MPL LIBRARY: Dependencies + + + + + +
Front Page / Technical Details / Dependencies
+
+

Dependencies

+

Besides Boost.Config headers, the MPL relies on three other header-only +libraries:

+ +

These dependencies are essential and cannot be eliminated. The +library's tests and examples may depend on some additional Boost +libraries such as Boost.Bind; unless you are interested in actually +compiling these files, you can safely ignore those dependencies.

+
+ + + + + diff --git a/doc/tutorial/details.html b/doc/tutorial/details.html new file mode 100644 index 0000000..6328469 --- /dev/null +++ b/doc/tutorial/details.html @@ -0,0 +1,119 @@ + + + + + + +THE BOOST MPL LIBRARY: Details + + + + + +
Front Page / Tutorial: Metafunctions and Higher-Order Metaprogramming / Details
+
+

Details

+

By now you should have a fairly complete view of the fundamental +concepts and language of both template metaprogramming in general +and of the Boost Metaprogramming Library. This section +reviews the highlights.

+
+
Metafunction forwarding.
+
The technique of using public derivation to +supply the nested type of a metafunction by accessing the one +provided by its base class.
+
Metafunction class.
+
The most basic way to formulate a compile-time +function so that it can be treated as polymorphic metadata; that +is, as a type. A metafunction class is a class with a nested +metafunction called apply.
+
MPL.
+

Most of this book's examples will use the Boost +Metaprogramming Library. Like the Boost type traits headers, +MPL +headers follow a simple convention:

+
+#include <boost/mpl/component-name.hpp>
+
+

If the component's name ends in an underscore, however, the +corresponding MPL header name does not include the trailing +underscore. For example, mpl::bool_ can be found in +<boost/mpl/bool.hpp>. Where the library deviates from this +convention, we'll be sure to point it out to you.

+
+
+ +
+
Higher-order function.
+
A function that operates on or returns a function. Making +metafunctions polymorphic with other metadata is a key +ingredient in higher-order metaprogramming.
+
Lambda expression.
+
Simply put, a lambda expression is callable metadata. Without +some form of callable metadata, higher-order metafunctions +would be impossible. Lambda expressions have two basic forms: +metafunction classes and placeholder expressions.
+
Placeholder expression.
+

A kind of lambda expression that, through the use of +placeholders, enables in-place partial metafunction +application and metafunction composition. As you will see +throughout this book, these features give us the truly amazing +ability to build up almost any kind of complex type computation +from more primitive metafunctions, right at its point of use:

+
+// find the position of a type x in some_sequence such that:
+//         x is convertible to 'int'
+//      && x is not 'char'
+//      && x is not a floating type
+typedef mpl::find_if<
+      some_sequence
+    , mpl::and_<
+          boost::is_convertible<_1,int>
+        , mpl::not_<boost::is_same<_1,char> >
+        , mpl::not_<boost::is_float<_1> >
+      >
+    >::type iter;
+
+

Placeholder expressions make good on the promise of algorithm reuse +without forcing us to write new metafunction classes. The +corresponding capability is often sorely missed in the runtime +world of the STL, since it is often much easier to write a loop +by hand than it is to use standard algorithms, despite their +correctness and efficiency advantages.

+
+
+ +
+
The lambda metafunction.
+
A metafunction that transforms a lambda expression into a +corresponding metafunction class. For detailed information on +lambda and the lambda evaluation process, +please see the the MPL reference manual.
+
The apply metafunction.
+
A metafunction that invokes its first argument, which must be a +lambda expression, on its remaining arguments. In general, to +invoke a lambda expression, you should always pass it to +mpl::apply along with the arguments you want to apply it +to in lieu of using lambda and invoking the result "manually."
+
Lazy evaluation.
+
A strategy of delaying evaluation until a result is +required, thereby avoiding any unneccessary computation and any +associated unneccessary errors. Metafunctions are only invoked +when we access their nested ::types, so we can supply all +of their arguments without performing any computation and +delay evaluation to the last possible moment.
+
+
+ + + + + diff --git a/doc/tutorial/dimensional-analysis.html b/doc/tutorial/dimensional-analysis.html new file mode 100644 index 0000000..c619c6e --- /dev/null +++ b/doc/tutorial/dimensional-analysis.html @@ -0,0 +1,85 @@ + + + + + + +THE BOOST MPL LIBRARY: Dimensional Analysis + + + + + +
Front Page / Tutorial: Metafunctions and Higher-Order Metaprogramming / Dimensional Analysis
+
+

Dimensional Analysis

+

The first rule of doing physical calculations +on paper is that the numbers being manipulated don't stand alone: +most quantities have attached dimensions, to be ignored at our +peril. As computations become more complex, keeping track of +dimensions is what keeps us from inadvertently assigning a mass to +what should be a length or adding acceleration to velocity — it +establishes a type system for numbers.

+

Manual checking of types is tedious, and as a result, it's also +error-prone. When human beings become bored, their attention +wanders and they tend to make mistakes. Doesn't type checking seem +like the sort of job a computer might be good at, though? If we +could establish a framework of C++ types for dimensions and +quantities, we might be able to catch errors in formulae before +they cause serious problems in the real world.

+

Preventing quantities with different dimensions from interoperating +isn't hard; we could simply represent dimensions as classes that +only work with dimensions of the same type. What makes this +problem interesting is that different dimensions can be combined, +via multiplication or division, to produce arbitrarily complex new +dimensions. For example, take Newton's law, which relates force to +mass and acceleration:

+
+F = ma
+

Since mass and acceleration have different dimensions, the +dimensions of force must somehow capture their combination. In +fact, the dimensions of acceleration are already just such a +composite, a change in velocity over time:

+
+dv/dt
+

Since velocity is just change in distance (l) over time (t), +the fundamental dimensions of acceleration are:

+
+(l/t)/t = l/t2
+

And indeed, acceleration is commonly measured in "meters per second +squared." It follows that the dimensions of force must be:

+
+ml/t2
+ +

and force is commonly measured in kg(m/s2), or +"kilogram-meters per second squared." When multiplying quantities +of mass and acceleration, we multiply their dimensions as well and +carry the result along, which helps us to ensure that the result is +meaningful. The formal name for this bookkeeping is dimensional +analysis, and our next task will be to implement its rules in the C++ +type system. John Barton and Lee Nackman were the first to show +how to do this in their seminal book, Scientific and Engineering +C++ [BN94]. We will recast their approach here in +metaprogramming terms.

+ + + + + +
[BN94]John J. Barton and Lee R. Nackman. Scientific and +Engineering C++: an Introduction with Advanced Techniques and +Examples. Reading, MA: Addison Wesley. ISBN +0-201-53393-6. 1994.
+ +
+ + + + + diff --git a/doc/tutorial/eti.html b/doc/tutorial/eti.html new file mode 100644 index 0000000..0a8fb17 --- /dev/null +++ b/doc/tutorial/eti.html @@ -0,0 +1,119 @@ + + + + + + +THE BOOST MPL LIBRARY: ETI + + + + + +
Front Page / Technical Details / Portability / ETI
+
+

ETI

+

In context of C++ template problems, ETI is an abbreviation for "Early +Template Instantiation" — a Microsoft Visual C++ - specific issue that +has been a barrier to any serious work with templates on this platform until +Microsoft developers fixed it in Visual C++ 7.1 (2003 .NET). Although the +problem is relatively easy to work around if the right techniques +are applied systematically through the codebase, the approach is definitely +tedious and time-consuming. So, if one day you discover that you are spending +too much time dealing with the issue, consider upgrading to the +newer version of the compiler. In fact, seriously consider it regardless. +The benefits of saved time, money and frustration are well worth the price.

+
+

The Problem

+

Here is a short demonstration of the issue with MSVC 6.x:

+
+template< typename F, typename T > struct apply1
+{
+    typedef typename F::template apply<T>::type type;
+};
+
+

Trying to compiling this innocent-looking code, we get:

+
+portability.cpp(4) : error C2903: 'apply' : symbol is neither a class template 
+            nor a function template
+        portability.cpp(5) : see reference to class template instantiation 
+            'apply1<F,T>' being compiled
+portability.cpp(4) : error C2143: syntax error : missing ',' before '<'
+        portability.cpp(5) : see reference to class template instantiation 
+            'apply1<F,T>' being compiled
+portability.cpp(4) : error C2059: syntax error : '<'
+        portability.cpp(5) : see reference to class template instantiation 
+            'apply1<F,T>' being compiled
+
+

The "symbol is neither a class template nor a function template" part of the +diagnostics is actually often an indication of ETI-related problems. Another +typical error message usually says something about nested type such-and-such +not being a member of a global namespace.

+

Both cases are two sides of the same compiler bug, which we call +"Early template instantiation": the compiler, for internal +purposes, in order to process class template definitions, +instantiates class templates with dummy template parameters +(int's). That can happen both during parsing of template +definitions (and such errors are most easy to identify and fix — +the template definition itself just doesn't compile; the example +above falls into this category), or later during template +instantiation, and these one are hard to detect — the bug will +only be triggered in some particular context.

+ +

ETI is always performed during parsing of the namespace-scope +template definition, which basically means that any template +definition that is rendered invalid by substituting its template +parameters by ints might not compile, as it happened with our +example:

+
+template< typename F, typename T > struct apply1
+{
+    // typedef typename F::template apply<T>::type type;
+    // ETI generates this: 
+    typedef typename int::template apply<int>::type type;
+};
+
+

If you compile this, you'll get exactly the same diagnostics as we've just seen.

+

Note that we've said "might not compile", because... well, the short answer is, +"it depends". We haven't analyzed things to the point that we could tell you the +exact condition when ETI leads to an error and when it doesn't, but +that's not very important anyway — if it's an error, you just fix it (we'll show you how +in a second), and if it's not, then you leave things as is. If one day the +potential issue turns into a real one, then you apply the workaround we are about +to give you.

+
+
+

The Symptoms

+

We've already looked at the typical diagnostics, so we won't repeat +ourselves. Instead we'll +just mention that many MSVC's INTERNAL COMPILER ERRORs (ICEs) are, in fact, caused +by an ETI-related problem somewhere deep down the instantiation stack.

+
+
+

The Solution

+

There is no way we can change the compiler's behavior in this case, so what we have +to do is to adjust to it and still make our templates do what we want. Surprisingly, +in most cases it's quite simple to achieve:

+
+// potentially unsafe
+template< typename F > struct apply0
+{
+    typedef typename F::type type;
+};
+
+// now ETI-safe
+template<> struct apply0<int>
+{
+    typedef int type;
+};
+
+

Since the original template could have never been instantiated with int, +providing a stub int specialization is completely innocent.

+ +
+
+ + + + + diff --git a/doc/tutorial/exercises.html b/doc/tutorial/exercises.html new file mode 100644 index 0000000..3388c45 --- /dev/null +++ b/doc/tutorial/exercises.html @@ -0,0 +1,103 @@ + + + + + + +THE BOOST MPL LIBRARY: Exercises + + + + + +
Front Page / Tutorial: Metafunctions and Higher-Order Metaprogramming / Exercises
+
+

Exercises

+
+
1-0.
+
Use BOOST_STATIC_ASSERT to add error checking to the binary +template presented in section 1.4.1 so +that binary<N>::value causes a compilation error if N +contains digits other than 0 or 1.
+
1-1.
+
Turn vector_c<int,1,2,3> into a type sequence with elements +(2,3,4) using transform.
+
1-2.
+
Turn vector_c<int,1,2,3> into a type sequence with elements +(1,4,9) using transform.
+
1-3.
+
Turn T into T**** by using twice twice.
+
1-4.
+
Turn T into T**** using twice on itself.
+
1-5.
+

There's still a problem with the dimensional analysis code in +section 1.1. +Hint: What happens when you do:

+
+f = f + m * a;
+
+

Repair this example using techniques shown in this +chapter.

+ +
+
1-6.
+
Build a lambda expression that has functionality equivalent to +twice. Hint: mpl::apply is a metafunction!
+
1-7*.
+

What do you think would be the semantics of the following +constructs:

+
+typedef mpl::lambda<mpl::lambda<_1> >::type t1;
+typedef mpl::apply<_1,mpl::plus<_1,_2> >::type t2;
+typedef mpl::apply<_1,std::vector<int> >::type t3;
+typedef mpl::apply<_1,std::vector<_1> >::type t4;
+typedef mpl::apply<mpl::lambda<_1>,std::vector<int> >::type t5;
+typedef mpl::apply<mpl::lambda<_1>,std::vector<_1> >::type t6;
+typedef mpl::apply<mpl::lambda<_1>,mpl::plus<_1,_2> >::type t7;
+typedef mpl::apply<_1,mpl::lambda< mpl::plus<_1,_2> > >::type t8;
+
+ +

Show the steps used to +arrive at your answers and write tests verifying your assumptions. +Did the library behavior match your reasoning? If not, analyze the +failed tests to discover the actual expression semantics. +Explain why your assumptions were different, what +behavior you find more coherent, and why.

+
+
1-8*.
+
Our dimensional analysis framework dealt with dimensions, but it +entirely ignored the issue of units. A length can be +represented in inches, feet, or meters. A force can be +represented in newtons or in kg m/sec2. Add the +ability to specify units and test your code. Try to make your +interface as syntactically friendly as possible for the user.
+
+ + + + + + +
+ + + + + diff --git a/doc/tutorial/handling-placeholders.html b/doc/tutorial/handling-placeholders.html new file mode 100644 index 0000000..4200c58 --- /dev/null +++ b/doc/tutorial/handling-placeholders.html @@ -0,0 +1,60 @@ + + + + + + +THE BOOST MPL LIBRARY: Handling Placeholders + + + + + +
Front Page / Tutorial: Metafunctions and Higher-Order Metaprogramming / Handling Placeholders
+
+

Handling Placeholders

+

Our implementation of twice already works with metafunction +classes. Ideally, we would +like it to work with placeholder expressions too, much the same as +mpl::transform allows us to pass either form. For example, we +would like to be able to write:

+
+template <class X>
+struct two_pointers
+    : twice<boost::add_pointer<_1>, X>
+{};
+
+ +

But when we look at the implementation of boost::add_pointer, +it becomes clear that the current definition of twice can't +work that way.

+
+template <class T>
+struct add_pointer
+{
+    typedef T* type;
+};
+
+ +

To be invokable by twice, boost::add_pointer<_1> would have +to be a metafunction class, along the lines of add_pointer_f. +Instead, it's just a nullary metafunction returning the almost +senseless type _1*. Any attempt to use two_pointers will +fail when apply1 reaches for a nested ::apply +metafunction in boost::add_pointer<_1> and finds that it +doesn't exist.

+

We've determined that we don't get the behavior we want +automatically, so what next? Since mpl::transform can do this +sort of thing, there ought to be a way for us to do it too — and +so there is.

+ +
+ + + + + diff --git a/doc/tutorial/higher-order.html b/doc/tutorial/higher-order.html new file mode 100644 index 0000000..ffc6008 --- /dev/null +++ b/doc/tutorial/higher-order.html @@ -0,0 +1,141 @@ + + + + + + +THE BOOST MPL LIBRARY: Higher-Order Metafunctions + + + + + +
Front Page / Tutorial: Metafunctions and Higher-Order Metaprogramming / Higher-Order Metafunctions
+
+

Higher-Order Metafunctions

+

In the previous section we used two different forms — +metafunction classes and placeholder expressions — +to pass and return metafunctions just like any other metadata. +Bundling metafunctions into "first class metadata" allows +transform to perform an infinite variety of different +operations: in our case, multiplication and division of dimensions. +Though the idea of using functions to manipulate other functions +may seem simple, its great power and flexibility [Hudak89] has +earned it a fancy title: higher-order functional programming. +A function that operates on another function is known as a +higher-order function. It follows that transform is a +higher-order +metafunction: a metafunction that operates on another metafunction.

+ + + + + +
[Hudak89]Paul Hudak. "Conception, Evolution, and Application of +Functional Programming Languages," ACM Computing Surveys 21, +no. 3 Pages: 359 - 411. New York: ACM Press. 1989. +ISSN:0360-0300. http://doi.acm.org/10.1145/72551.72554.
+

Now that we've seen the power of higher-order metafunctions at +work, it would be good to be able to create new ones. In order to +explore the basic mechanisms, let's try a simple example. Our task +is to write a metafunction called twice, which — given a unary +metafunction f and arbitrary metadata x — computes:

+
+twice(f, x) := f(f(x))
+

This might seem like a trivial example, and in fact it is. You +won't find much use for twice in real code. We hope you'll +bear with us anyway: Because it doesn't do much more than accept +and invoke a metafunction, twice captures all the essential +elements of "higher-orderness" without any distracting details.

+

If f is a metafunction class, the definition of twice is +straightforward:

+
+template <class F, class X>
+struct twice
+{
+    typedef typename F::template apply<X>::type once;    // f(x)
+    typedef typename F::template apply<once>::type type; // f(f(x))
+};
+
+ + +

Or, applying metafunction forwarding:

+
+template <class F, class X>
+struct twice
+  : F::template apply<
+       typename F::template apply<X>::type
+    >
+{};
+
+ +
+

C++ Language Note

+

The C++ standard requires the template keyword when we use a +dependent name that refers to a member template. +F::apply may or may not name a template, depending on the +particular F that is passed. See the book's Appendix B for more +information about template.

+
+

Given the need to sprinkle our code with the template keyword, +it would be nice to reduce the syntactic burden of invoking +metafunction classes. As usual, the solution is to factor the +pattern into a metafunction:

+
+template <class UnaryMetaFunctionClass, class Arg>
+struct apply1
+  : UnaryMetaFunctionClass::template apply<Arg>
+{};
+
+

Now twice is just:

+
+template <class F, class X>
+struct twice
+  : apply1<F, typename apply1<F,X>::type>
+{};
+
+

To see twice at work, we can apply it to a little metafunction +class built around the add_pointer metafunction:

+
+struct add_pointer_f
+{
+    template <class T>
+    struct apply : boost::add_pointer<T> {};
+};
+
+ +

Now we can use twice with add_pointer_f to build +pointers-to-pointers:

+
+BOOST_STATIC_ASSERT((
+    boost::is_same<
+         twice<add_pointer_f, int>::type
+       , int**
+    >::value
+));
+
+ +
+ + + + + diff --git a/doc/tutorial/implementing-addition-and.html b/doc/tutorial/implementing-addition-and.html new file mode 100644 index 0000000..a07f0b5 --- /dev/null +++ b/doc/tutorial/implementing-addition-and.html @@ -0,0 +1,56 @@ + + + + + + +THE BOOST MPL LIBRARY: Implementing Addition and Subtraction + + + + + +
Front Page / Tutorial: Metafunctions and Higher-Order Metaprogramming / Dimensional Analysis / Implementing Addition and Subtraction
+
+

Implementing Addition and Subtraction

+

We can now easily write the rules for addition and subtraction, +since the dimensions of the arguments must always match.

+
+template <class T, class D>
+quantity<T,D>
+operator+(quantity<T,D> x, quantity<T,D> y)
+{
+  return quantity<T,D>(x.value() + y.value());
+}
+
+template <class T, class D>
+quantity<T,D>
+operator-(quantity<T,D> x, quantity<T,D> y)
+{
+  return quantity<T,D>(x.value() - y.value());
+}
+
+ +

These operators enable us to write code like:

+
+quantity<float,length> len1( 1.0f );
+quantity<float,length> len2( 2.0f );
+
+len1 = len1 + len2;   // OK
+
+ +

but prevent us from trying to add incompatible dimensions:

+
+len1 = len2 + quantity<float,mass>( 3.7f ); // error
+
+ +
+ + + + + diff --git a/doc/tutorial/implementing-division.html b/doc/tutorial/implementing-division.html new file mode 100644 index 0000000..0f6d58e --- /dev/null +++ b/doc/tutorial/implementing-division.html @@ -0,0 +1,163 @@ + + + + + + +THE BOOST MPL LIBRARY: Implementing Division + + + + + +
Front Page / Tutorial: Metafunctions and Higher-Order Metaprogramming / Dimensional Analysis / Implementing Division
+
+

Implementing Division

+

Division is similar to multiplication, but instead of adding +exponents, we must subtract them. Rather than writing out a near +duplicate of plus_f, we can use the following trick to make +minus_f much simpler:

+
+struct minus_f
+{
+    template <class T1, class T2>
+    struct apply
+      : mpl::minus<T1,T2> {};
+};
+
+ +

Here minus_f::apply uses inheritance to expose the nested +type of its base class, mpl::minus, so we don't have to +write:

+
+typedef typename ...::type type
+
+ +

We don't have to write +typename here (in fact, it would be illegal), because the +compiler knows that dependent names in apply's initializer +list must be base classes. [2] This powerful +simplification is known as metafunction forwarding; we'll apply +it often as the book goes on. [3]

+ + + + + +
[2]In case you're wondering, the same approach could +have been applied to plus_f, but since it's a little subtle, +we introduced the straightforward but verbose formulation +first.
+ + + + + +
[3]Users of EDG-based compilers should consult the book's Appendix C +for a caveat about metafunction forwarding. You can tell whether +you have an EDG compiler by checking the preprocessor symbol +__EDG_VERSION__, which is defined by all EDG-based compilers.
+

Syntactic tricks notwithstanding, writing trivial classes to wrap +existing metafunctions is going to get boring pretty quickly. Even +though the definition of minus_f was far less verbose than that +of plus_f, it's still an awful lot to type. Fortunately, MPL gives +us a much simpler way to pass metafunctions around. Instead of +building a whole metafunction class, we can invoke transform +this way:

+
+typename mpl::transform<D1,D2, mpl::minus<_1,_2> >::type
+
+ +

Those funny looking arguments (_1 and _2) are known as +placeholders, and they signify that when the transform's +BinaryOperation is invoked, its first and second arguments will +be passed on to minus in the positions indicated by _1 and +_2, respectively. The whole type mpl::minus<_1,_2> is +known as a placeholder expression.

+
+

Note

+

MPL's placeholders are in the mpl::placeholders +namespace and defined in boost/mpl/placeholders.hpp. In +this book we will usually assume that you have written:

+
+#include<boost/mpl/placeholders.hpp>
+using namespace mpl::placeholders;
+
+

so that they can be accessed without qualification.

+
+ +

Here's our division operator written using placeholder +expressions:

+
+template <class T, class D1, class D2>
+quantity< 
+    T
+  , typename mpl::transform<D1,D2,mpl::minus<_1,_2> >::type
+>
+operator/(quantity<T,D1> x, quantity<T,D2> y)
+{
+   typedef typename 
+     mpl::transform<D1,D2,mpl::minus<_1,_2> >::type dim;
+
+   return quantity<T,dim>( x.value() / y.value() );
+}
+
+ +

This code is considerably simpler. We can simplify it even further +by factoring the code that calculates the new dimensions into its +own metafunction:

+
+template <class D1, class D2>
+struct divide_dimensions
+  : mpl::transform<D1,D2,mpl::minus<_1,_2> > // forwarding again
+{};
+
+template <class T, class D1, class D2>
+quantity<T, typename divide_dimensions<D1,D2>::type>
+operator/(quantity<T,D1> x, quantity<T,D2> y)
+{
+   return quantity<T, typename divide_dimensions<D1,D2>::type>(
+      x.value() / y.value());
+}
+
+ +

Now we can verify our "force-on-a-laptop" computation by reversing +it, as follows:

+
+quantity<float,mass> m2 = f/a;
+float rounding_error = std::abs((m2 - m).value());
+
+ +

If we got everything right, rounding_error should be very close +to zero. These are boring calculations, but they're just the sort +of thing that could ruin a whole program (or worse) if you got them +wrong. If we had written a/f instead of f/a, there would have +been a compilation error, preventing a mistake from propagating +throughout our program.

+
+ + + + + diff --git a/doc/tutorial/implementing.html b/doc/tutorial/implementing.html new file mode 100644 index 0000000..67ca292 --- /dev/null +++ b/doc/tutorial/implementing.html @@ -0,0 +1,265 @@ + + + + + + +THE BOOST MPL LIBRARY: Implementing Multiplication + + + + + +
Front Page / Tutorial: Metafunctions and Higher-Order Metaprogramming / Dimensional Analysis / Implementing Multiplication
+
+

Implementing Multiplication

+

Multiplication is a bit more complicated than addition and +subtraction. So far, the dimensions of the arguments and results have +all been identical, but when multiplying, the result will usually +have different dimensions from either of the arguments. For +multiplication, the relation:

+
+(xa)(xb) == x (a + b)
+ +

implies that the exponents of the result dimensions should be the +sum of corresponding exponents from the argument +dimensions. Division is similar, except that the sum is replaced by +a difference.

+

To combine corresponding elements from two sequences, we'll use +MPL's transform algorithm. transform is a metafunction +that iterates through two input sequences in parallel, passing an +element from each sequence to an arbitrary binary metafunction, and +placing the result in an output sequence.

+
+template <class Sequence1, class Sequence2, class BinaryOperation>
+struct transform;  // returns a Sequence
+
+

The signature above should look familiar if you're acquainted with the +STL transform algorithm that accepts two runtime sequences +as inputs:

+
+template <
+    class InputIterator1, class InputIterator2
+  , class OutputIterator, class BinaryOperation
+>
+void transform(
+    InputIterator1 start1, InputIterator2 finish1
+  , InputIterator2 start2
+  , OutputIterator result, BinaryOperation func);
+
+ +

Now we just need to pass a BinaryOperation that adds or +subtracts in order to multiply or divide dimensions with +mpl::transform. If you look through the the MPL reference manual, you'll +come across plus and minus metafunctions that do just what +you'd expect:

+
+#include <boost/static_assert.hpp>
+#include <boost/mpl/plus.hpp>
+#include <boost/mpl/int.hpp>
+namespace mpl = boost::mpl;
+
+BOOST_STATIC_ASSERT(( 
+    mpl::plus<
+        mpl::int_<2>
+      , mpl::int_<3>
+    >::type::value == 5
+));
+
+ + + +

At this point it might seem as though we have a solution, but we're +not quite there yet. A naive attempt to apply the transform +algorithm in the implementation of operator* yields a compiler +error:

+
+#include <boost/mpl/transform.hpp>
+
+template <class T, class D1, class D2>
+quantity< 
+    T
+  , typename mpl::transform<D1,D2,mpl::plus>::type
+>
+operator*(quantity<T,D1> x, quantity<T,D2> y) { ... }
+
+ + +

It fails because the protocol says that metafunction arguments +must be types, and plus is not a type, but a class template. +Somehow we need to make metafunctions like plus fit the +metadata mold.

+

One natural way to introduce polymorphism between metafunctions and +metadata is to employ the wrapper idiom that gave us polymorphism +between types and integral constants. Instead of a nested integral +constant, we can use a class template nested within a +metafunction class:

+
+struct plus_f
+{
+    template <class T1, class T2>
+    struct apply
+    {
+       typedef typename mpl::plus<T1,T2>::type type;
+    };
+};
+
+
+

Definition

+

A Metafunction Class is a class with a publicly accessible +nested metafunction called apply.

+
+

Whereas a metafunction is a template but not a type, a +metafunction class wraps that template within an ordinary +non-templated class, which is a type. Since metafunctions +operate on and return types, a metafunction class can be passed as +an argument to, or returned from, another metafunction.

+

Finally, we have a BinaryOperation type that we can pass to +transform without causing a compilation error:

+
+template <class T, class D1, class D2>
+quantity< 
+    T
+  , typename mpl::transform<D1,D2,plus_f>::type  // new dimensions
+>
+operator*(quantity<T,D1> x, quantity<T,D2> y)
+{
+    typedef typename mpl::transform<D1,D2,plus_f>::type dim;
+    return quantity<T,dim>( x.value() * y.value() );
+}
+
+

Now, if we want to compute the force exterted by gravity on a 5 kilogram +laptop computer, that's just the acceleration due to gravity (9.8 +m/sec2) times the mass of the laptop:

+
+quantity<float,mass> m(5.0f);
+quantity<float,acceleration> a(9.8f);
+std::cout << "force = " << (m * a).value();
+
+ +

Our operator* multiplies the runtime values (resulting in +6.0f), and our metaprogram code uses transform to sum the +meta-sequences of fundamental dimension exponents, so that the +result type contains a representation of a new list of exponents, +something like:

+
+mpl::vector_c<int,1,1,-2,0,0,0,0>
+
+ + +

However, if we try to write:

+
+quantity<float,force> f = m * a;
+
+ + +

we'll run into a little problem. Although the result of +m * a does indeed represent a force with exponents of mass, +length, and time 1, 1, and -2 respectively, the type returned by +transform isn't a specialization of vector_c. Instead, +transform works generically on the elements of its inputs and +builds a new sequence with the appropriate elements: a type with +many of the same sequence properties as +mpl::vector_c<int,1,1,-2,0,0,0,0>, but with a different C++ type +altogether. If you want to see the type's full name, you can try +to compile the example yourself and look at the error message, but +the exact details aren't important. The point is that +force names a different type, so the assignment above will fail.

+

In order to resolve the problem, we can add an implicit conversion +from the multiplication's result type to quantity<float,force>. +Since we can't predict the exact types of the dimensions involved +in any computation, this conversion will have to be templated, +something like:

+
+template <class T, class Dimensions>
+struct quantity
+{
+    // converting constructor
+    template <class OtherDimensions>
+    quantity(quantity<T,OtherDimensions> const& rhs)
+      : m_value(rhs.value())
+    {
+    }
+    ...
+
+ +

Unfortunately, such a general conversion undermines our whole +purpose, allowing nonsense such as:

+
+// Should yield a force, not a mass!
+quantity<float,mass> bogus = m * a;
+
+ +

We can correct that problem using another MPL algorithm, +equal, which tests that two sequences have the same elements:

+
+template <class OtherDimensions>
+quantity(quantity<T,OtherDimensions> const& rhs)
+  : m_value(rhs.value())
+{
+    BOOST_STATIC_ASSERT((
+       mpl::equal<Dimensions,OtherDimensions>::type::value
+    ));
+}
+
+ +

Now, if the dimensions of the two quantities fail to match, the +assertion will cause a compilation error.

+
+ + + + + diff --git a/doc/tutorial/incomplete-support-for.html b/doc/tutorial/incomplete-support-for.html new file mode 100644 index 0000000..c523114 --- /dev/null +++ b/doc/tutorial/incomplete-support-for.html @@ -0,0 +1,126 @@ + + + + + + +THE BOOST MPL LIBRARY: Incomplete Support for Lambda Expressions + + + + + +
Front Page / Technical Details / Portability / Incomplete Support for Lambda Expressions
+
+

Incomplete Support for Lambda Expressions

+

Seasoned MPL users will agree with us that if there is +anything in the MPL that is seemingly magical both in power and +its nature, then it's MPL lambda expressions. In reality, the +mechanism that bring this to life is very straightforward and +probably can be explained to anyone generally familiar with C++ +templates in less than 10 minutes.

+ + +

Unfortunately, this mechanism also happens to rely on support for +partial template specialization and template template parameters. +Among the so-called deficient compilers — basically, most of the +compilers released before the year 2000 — the chances are poor +that you'll find complete support for both of these features. +Please see our compatibility table for the list of the products +which fall into this category.

+

Although it's not possible to implement fully transparent lambda +expressions without these two features, a slightly more limited +implementation that requires some manual assistance from the +metafunction author is possible. This section describes the manual +work required and the limitations of the result.

+
+

The Problem

+

If your compiler falls into the "deficient" category, the following +valid MPL metaprogram will fail to compile for you:

+
+#include <boost/mpl/apply.hpp>
+
+using namespace boost::mpl;
+
+template< typename T > struct add_const
+{
+    typedef T const type;
+};
+
+typedef apply1< add_const<_1>,int >::type t; // t == int const
+
+

Worse yet, chances are it wil fail with a diagnostic backtrace +leading you into the inside of the library and possibly creating an +impression that there's something's wrong there. The fact is, both +the program and the library are defect free (for the +purpose of this particular demonstraction), and it's your compiler +that is to blame.

+
+
+

The Solution

+

As previously mentioned, the solution requires some work from +metafunction authors, but for the users of those metafunctions, the +result is relatively transparent. Here's what we have to do to our +earlier example:

+
+#include <boost/mpl/apply.hpp>
+#include <boost/mpl/aux_/lambda_support.hpp>
+
+using namespace boost::mpl;
+
+template< typename T > struct add_const
+{
+    typedef T const type;
+    BOOST_MPL_AUX_LAMBDA_SUPPORT(1, add_const, (T))
+};
+
+typedef apply1< add_const<_1>,int >::type t; // t == int const
+
+

With these two modifications, now the compiler that has been barking at us now +happily accepts it. "Hey, that's not that bad at all!" you might say. Just put a +little macro inside and be happy again.

+
+
+

Limitations

+

Unfortunately, that's not quite the end of the story. There are +still cases where the above approach will fail and we will have to +resort to writing out-of-line metafunction class. Here are the +details:

+
+

To make the lambda expression work without partial template +specialization and +template template parameters, the MPL has to implement some other way of +pulling apart the template instantiations' expression tree, and the only way +to do it is through an intrusive metafunction introspection +mechanism. That's what hidden behind the BOOST_MPL_AUX_LAMBDA_SUPPORT macro +we've seen above.

+

But then, after we've got the information we need (the metafunction's arity +and its exact template arguments) stored inside the metafunction itself, +the only way for the library to access it is to look inside the metafunction. +The latter, in its turn, means instantiating the metafunction, prematurely, +before the actuall call, with one or more placeholder arguments. This last +part is a potential problem.

+
+

In other words, the mechanism works as long as your metafunction is +"placeholder-safe" (can be safely instantiated on placeholder +arguments), which comes down to the follwing two criteria:

+
    +
  1. The metafunction doesn't access its arguments' nested members, or
  2. +
  3. The only accessed members are types named ::tag or ::type (the +placeholders do contain these).
  4. +
+

If these two hold, you can safely put BOOST_MPL_AUX_LAMBDA_SUPPORT inside +your metafunction and forget about the issue. If not, your are out of luck and +probably have to write a metafunction class instead.

+

The good news are that most of the MPL's own metafunctions and Boost.Type Traits +templates are "placeholder-safe" and have the workaround applied to them, so +even on broken compilers things "just work" in about 90% of use cases.

+

Please refer to the MPL reference manual for the details on the +BOOST_MPL_AUX_LAMBDA_SUPPORT macro.

+
+
+ + + + + diff --git a/doc/tutorial/iterator-protocol.html b/doc/tutorial/iterator-protocol.html new file mode 100644 index 0000000..f90b446 --- /dev/null +++ b/doc/tutorial/iterator-protocol.html @@ -0,0 +1,56 @@ + + + + + + +THE BOOST MPL LIBRARY: Iterator Protocol + + + + + +
Front Page / Changelog & History / Changes in Boost 1.32.0 Release / Iterator Protocol
+
+

Iterator Protocol

+

The library no longer guarantees or relies on the direct presence +of advance / distance / next / prior / type +members in iterator types; the following table summarises the new +requirements:

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
BeforeNow
i::typederef<i>::type
i::nextnext<i>::type
i::priorprior<i>::type
i::advance<n>::typeadvance<i,n>::type
i::distance<j>::typedistance<i,j>::type
i::categoryi::category
+
+ + + + + diff --git a/doc/tutorial/lambda-and-non.html b/doc/tutorial/lambda-and-non.html new file mode 100644 index 0000000..718aa9f --- /dev/null +++ b/doc/tutorial/lambda-and-non.html @@ -0,0 +1,47 @@ + + + + + + +THE BOOST MPL LIBRARY: Lambda and Non-Metafunction Templates + + + + + +
Front Page / Tutorial: Metafunctions and Higher-Order Metaprogramming / Lambda Details / Lambda and Non-Metafunction Templates
+
+

Lambda and Non-Metafunction Templates

+

There is just one detail of placeholder expressions that we haven't +discussed yet. MPL uses a special rule to make it easier to +integrate ordinary templates into metaprograms: After all of the +placeholders have been replaced with actual +arguments, if the resulting template specialization X doesn't +have a nested ::type, the result is just +X itself.

+

For example, mpl::apply<std::vector<_>, T> is always just +std::vector<T>. If it weren't for this behavior, we would +have to build trivial metafunctions to create ordinary template +specializations in lambda expressions:

+
+// trivial std::vector generator
+template<class U> 
+struct make_vector { typedef std::vector<U> type; };
+
+typedef mpl::apply<make_vector<_>, T>::type vector_of_t;
+
+

Instead, we can simply write:

+
+typedef mpl::apply<std::vector<_>, T>::type vector_of_t;
+
+ +
+ + + + + diff --git a/doc/tutorial/lambda-details.html b/doc/tutorial/lambda-details.html new file mode 100644 index 0000000..f453a44 --- /dev/null +++ b/doc/tutorial/lambda-details.html @@ -0,0 +1,30 @@ + + + + + + +THE BOOST MPL LIBRARY: Lambda Details + + + + + +
Front Page / Tutorial: Metafunctions and Higher-Order Metaprogramming / Lambda Details
+
+

Lambda Details

+

Now that you have an idea of the semantics of MPL's lambda +facility, let's formalize that understanding and look at things a +little more deeply.

+ +
+ + + + + diff --git a/doc/tutorial/metafunction-composition.html b/doc/tutorial/metafunction-composition.html new file mode 100644 index 0000000..5dcec70 --- /dev/null +++ b/doc/tutorial/metafunction-composition.html @@ -0,0 +1,39 @@ + + + + + + +THE BOOST MPL LIBRARY: Metafunction Composition + + + + + +
Front Page / Tutorial: Metafunctions and Higher-Order Metaprogramming / More Lambda Capabilities / Metafunction Composition
+
+

Metafunction Composition

+

Lambda expressions can also be used to assemble more interesting +computations from simple metafunctions. For example, the following +expression, which multiplies the sum of two numbers by their +difference, is a composition of the three metafunctions multiplies, +plus, and minus:

+
+mpl::multiplies<mpl::plus<_1,_2>, mpl::minus<_1,_2> >
+
+ +

When evaluating a lambda expression, MPL checks to see if any of its +arguments are themselves lambda expressions, and evaluates each one +that it finds. The results of these inner evaluations are substituted +into the outer expression before it is evaluated.

+
+ + + + + diff --git a/doc/tutorial/miscellaneous.html b/doc/tutorial/miscellaneous.html new file mode 100644 index 0000000..5ce241d --- /dev/null +++ b/doc/tutorial/miscellaneous.html @@ -0,0 +1,35 @@ + + + + + + +THE BOOST MPL LIBRARY: Miscellaneous + + + + + +
Front Page / Changelog & History / Changes in Boost 1.32.0 Release / Miscellaneous
+
+

Miscellaneous

+
    +
  1. vector has been re-implemented to support constant-time +insertion at both the beginning and the end. For example, this is now +well-formed for a vector v:

    +
    +typedef push_back<v,int>::type v1;
    +typedef push_front<v1,int>::type v2;
    +
    +
  2. +
  3. The interfaces of some sequence building algorithms such as +copy have been changed. Please see the reference manual for the +details of the new interface.

    +
  4. +
+
+ + + + + diff --git a/doc/tutorial/more-lambda-capabilities.html b/doc/tutorial/more-lambda-capabilities.html new file mode 100644 index 0000000..e5ecc11 --- /dev/null +++ b/doc/tutorial/more-lambda-capabilities.html @@ -0,0 +1,29 @@ + + + + + + +THE BOOST MPL LIBRARY: More Lambda Capabilities + + + + + +
Front Page / Tutorial: Metafunctions and Higher-Order Metaprogramming / More Lambda Capabilities
+
+

More Lambda Capabilities

+

Lambda expressions provide much more than just the ability to pass a +metafunction as an argument. The two capabilities described next +combine to make lambda expressions an invaluable part of almost every +metaprogramming task.

+ +
+ + + + + diff --git a/doc/tutorial/numeric-metafunction.html b/doc/tutorial/numeric-metafunction.html new file mode 100644 index 0000000..486e1f6 --- /dev/null +++ b/doc/tutorial/numeric-metafunction.html @@ -0,0 +1,71 @@ + + + + + + +THE BOOST MPL LIBRARY: Numeric Metafunction Protocol/Infrastructure + + + + + +
Front Page / Changelog & History / Changes in Boost 1.32.0 Release / Numeric Metafunction Protocol/Infrastructure
+
+

Numeric Metafunction Protocol/Infrastructure

+

The arithmetic, comparison and bitwise metafunctions are now +polymorphic, and can operate on a variety of numeric types, +including rational, fixed-point and complex numbers. They allow +mixed arithmetic, meaning that you can perform an operation on +arguments of different types, and the result will yeild the +largest/most general of the argument types. The infrastructure +allows user-defined numeric types to be freely intermixed with +predefined library types. See +http://cvs.sourceforge.net/viewcvs.py/boost/boost/libs/mpl/test/numeric_ops.cpp?view=markup +for an illustrative example, and the reference manual for +the formal infrastructure specification.

+

If you were using MPL numeric metafunctions on your own integral +wrapper class similar to mpl::int_, you can plug your class +into the new infrustructure by extending it with the following +member:

+
+typedef mpl::integral_c_tag tag;
+
+

For example:

+ ++++ + + + + + + + + + + +
BeforeNow
+template< int n > struct my_int
+{
+    static int const value = n;
+    typedef my_int type;
+};
+
+
+template< int n > struct my_int
+{
+    typedef mpl::integral_c_tag tag;
+    static int const value = n;
+    typedef my_int type;
+};
+
+
+
+ + + + + diff --git a/doc/tutorial/partial-metafunction.html b/doc/tutorial/partial-metafunction.html new file mode 100644 index 0000000..5ba2d0f --- /dev/null +++ b/doc/tutorial/partial-metafunction.html @@ -0,0 +1,41 @@ + + + + + + +THE BOOST MPL LIBRARY: Partial Metafunction Application + + + + + +
Front Page / Tutorial: Metafunctions and Higher-Order Metaprogramming / More Lambda Capabilities / Partial Metafunction Application
+
+

Partial Metafunction Application

+

Consider the lambda expression mpl::plus<_1,_1>. A single +argument is directed to both of plus's parameters, thereby +adding a number to itself. Thus, a binary metafunction, +plus, is used to build a unary lambda expression. In other +words, we've created a whole new computation! We're not done yet, +though: By supplying a non-placeholder as one of the arguments, we +can build a unary lambda expression that adds a fixed value, say +42, to its argument:

+
+mpl::plus<_1, mpl::int_<42> >
+
+ +

The process of binding argument values to a subset of a function's +parameters is known in the world of functional programming as +partial function application.

+
+ + + + + diff --git a/doc/tutorial/physical-structure.html b/doc/tutorial/physical-structure.html new file mode 100644 index 0000000..80d73b9 --- /dev/null +++ b/doc/tutorial/physical-structure.html @@ -0,0 +1,32 @@ + + + + + + +THE BOOST MPL LIBRARY: Physical Structure + + + + + +
Front Page / Technical Details / Physical Structure
+
+

Physical Structure

+

The library uses a fine-grained header structure with one header per public +component (class/function template), with the header named after the component. For example, +boost::mpl::apply is defined in the header <boost/mpl/apply.hpp>. This +scheme ensures both that we don't pay for what we don't use in terms of compilation time +and header dependencies, and frees us from memorizing the +relationship between a given header and the components it +provides. For entities that are likely to be used together, +such as arithmetic +metafunctions (plus, minus, times, et. al.), the library also supplies +appropriately-named composite headers +(<boost/mpl/airthmetic.hpp>) as a convenience.

+
+ + + + + diff --git a/doc/tutorial/placeholder-expression.html b/doc/tutorial/placeholder-expression.html new file mode 100644 index 0000000..55fced9 --- /dev/null +++ b/doc/tutorial/placeholder-expression.html @@ -0,0 +1,97 @@ + + + + + + +THE BOOST MPL LIBRARY: Placeholder Expression Definition + + + + + +
Front Page / Tutorial: Metafunctions and Higher-Order Metaprogramming / Lambda Details / Placeholder Expression Definition
+
+

Placeholder Expression Definition

+

Now that you know just what placeholder means, we can define +placeholder expression:

+
+

Definition

+

A placeholder expression is either:

+
+
+
    +
  • a placeholder
  • +
+
+

or

+
+
    +
  • a template specialization with at least one argument that +is a placeholder expression.
  • +
+
+
+
+

In other words, a placeholder expression always involves a +placeholder.

+ +
+ + + + + diff --git a/doc/tutorial/placeholders.html b/doc/tutorial/placeholders.html new file mode 100644 index 0000000..1d9dfa6 --- /dev/null +++ b/doc/tutorial/placeholders.html @@ -0,0 +1,162 @@ + + + + + + +THE BOOST MPL LIBRARY: Placeholders + + + + + +
Front Page / Tutorial: Metafunctions and Higher-Order Metaprogramming / Lambda Details / Placeholders
+
+

Placeholders

+

The definition of "placeholder" may surprise you:

+
+

Definition

+

A placeholder is a metafunction class of the form mpl::arg<X>.

+
+
+

Implementation

+

The convenient names _1, _2,... _5 are actually +typedefs for specializations of mpl::arg that simply +select the Nth argument for any N. [6] The +implementation of placeholders looks something like this:

+ + + + + +
[6]MPL provides five placeholders by default. See +the Configuration Macros section of the MPL reference manual for a +description of how to change the number of placeholders +provided.
+
+namespace boost { namespace mpl { namespace placeholders {
+
+template <int N> struct arg; // forward declarations
+struct void_;
+
+template <>
+struct arg<1>
+{
+    template <
+      class A1, class A2 = void_, ... class Am = void_>
+    struct apply
+    {
+        typedef A1 type; // return the first argument
+    };
+};
+typedef arg<1> _1;
+
+template <>
+struct arg<2>
+{
+    template <
+      class A1, class A2, class A3 = void_, ...class Am = void_
+    >
+    struct apply
+    {
+        typedef A2 type; // return the second argument
+    };
+};
+typedef arg<2> _2;
+
+more specializations and typedefs...
+
+}}}
+
+ +

Remember that invoking a metafunction class is the same as invoking +its nested apply metafunction. When a placeholder in a lambda +expression is evaluated, it is invoked on the expression's actual +arguments, returning just one of them. The results are then +substituted back into the lambda expression and the evaluation +process continues.

+
+
+

The Unnamed Placeholder

+

There's one special placeholder, known as the unnamed +placeholder, that we haven't yet defined:

+
+namespace boost { namespace mpl { namespace placeholders {
+
+typedef arg<-1> _; // the unnamed placeholder
+
+}}}
+
+ +

The details of its implementation aren't important; all you really +need to know about the unnamed placeholder is that it gets special +treatment. When a lambda expression is being transformed into a +metafunction class by mpl::lambda,

+
+the nth appearance of the unnamed placeholder in a given +template specialization is replaced with _n.
+

So, for example, every row of Table 1.1 +below contains two equivalent lambda expressions.

+ + ++++ + + + + + + + + + + + +
Unnamed Placeholder Semantics
+mpl::plus<_,_>
+
+
+mpl::plus<_1,_2>
+
+
+boost::is_same<
+    _
+  , boost::add_pointer<_>
+>
+
+
+boost::is_same<
+    _1
+  , boost::add_pointer<_1>
+>
+
+
+mpl::multiplies<
+   mpl::plus<_,_>
+ , mpl::minus<_,_>
+>
+
+
+mpl::multiplies<
+   mpl::plus<_1,_2>
+ , mpl::minus<_1,_2>
+>
+
+
+ +

Especially when used in simple lambda expressions, the unnamed +placeholder often eliminates just enough syntactic "noise" to +significantly improve readability.

+
+
+ + + + + diff --git a/doc/tutorial/portability.html b/doc/tutorial/portability.html new file mode 100644 index 0000000..78a91b4 --- /dev/null +++ b/doc/tutorial/portability.html @@ -0,0 +1,135 @@ + + + + + + +THE BOOST MPL LIBRARY: Portability + + + + + +
Front Page / Technical Details / Portability
+
+

Portability

+

It has always been a major goal of MPL development that a program +using the MPL should compile and run without modification on a wide +variety of compilers. To this end, the library goes to great +lengths to hide the quirks of less-than-perfect compilers. Of +course, there is only that much that you can do about an utterly +broken compiler. This section describes the places where those +quirks "leak out" of the library abstraction layer, and what you can +do about it when they do.

+

With respect to MPL compatibility we divide C++ compilers roughly +into three categories:

+
    +
  1. Reasonably conforming compilers that "just work" with the MPL.
  2. +
  3. Not-so-conforming compilers that work but require some workarounds in user code.
  4. +
  5. Compilers that are so broken that it's not practical to use them for any serious +metaprogramming work.
  6. +
+

We haven't tested every compiler in existence (simply because we don't have access to +all of them), but chances are the table below +will give you the information you are looking for. Please note that +the fact that one version of a compiler appears +in this list as "Not supported" does not mean that future versions are also +unworkable — some vendors are working hard to correct the +problems... and, as of this writing (late 2004), some are not.

+

Please keep in mind that this is not a complete list!

+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CompilerVersionsCategoryProblematic Areas (if any)
Borland C++5.6.4BLambda Expressions, Integral Constant Expressions
Borland C++5.6.1CNot supported
Comeau C/C++4.2.45, +4.3.3A 
Compaq C++ (Tru64 UNIX)6.5A 
GCC3.2.2, +3.3.1, 3.4A 
GCC2.95.3BIntegral Constant Expressions
HP aCC3.55CNot supported
Intel C++7.1, 8.0A 
Metrowerks CodeWarrior8.3, 9.2A 
Microsoft Visual C++7.1A 
Microsoft Visual C++6.0 sp5, +7.0BLambda Expressions, ETI, Integral Constant Expressions
SGI MIPSpro7.3BIntegral Constant Expressions
Sun CC5.6CNot supported
+ +
+ + + + + diff --git a/doc/tutorial/reference-manual.html b/doc/tutorial/reference-manual.html new file mode 100644 index 0000000..9f192ad --- /dev/null +++ b/doc/tutorial/reference-manual.html @@ -0,0 +1,28 @@ + + + + + + +THE BOOST MPL LIBRARY: Reference Manual + + + + + +
Front Page / Reference Manual
+
+

Reference Manual

+

The MPL reference manual is an annotated formal specification of the +library's public interface. The manual is available in two forms:

+
    +
  • A fully cross-referenced set of HTML pages.
  • +
  • A cross-referenced, printer-ready PDF.
  • +
+

Please choose the form that is most convenient for you, and enjoy!

+
+ + + + + diff --git a/doc/tutorial/renaming-cleanup.html b/doc/tutorial/renaming-cleanup.html new file mode 100644 index 0000000..96a7f37 --- /dev/null +++ b/doc/tutorial/renaming-cleanup.html @@ -0,0 +1,78 @@ + + + + + + +THE BOOST MPL LIBRARY: Renaming/Cleanup + + + + + +
Front Page / Changelog & History / Changes in Boost 1.32.0 Release / Renaming/Cleanup
+
+

Renaming/Cleanup

+
    +
  1. The apply_if metafunction has been renamed to eval_if.

    +
  2. +
  3. All _backward algorithm counterparts have been renamed to use reverse_ +prefix; e.g. fold_backward became reverse_fold.

    +
  4. +
  5. The <boost/mpl/aux_/has_xxx.hpp> header has been made public and became +<boost/mpl/has_xxx.hpp>; correspondingly, the BOOST_MPL_NO_AUX_HAS_XXX +macro was renamed to BOOST_MPL_CFG_NO_HAS_XXX.

    +
  6. +
  7. <boost/mpl/assert_is_same.hpp> header has been replaced by a more +general <mpl/assert.hpp>; the new asserts provide a significantly +higher-quality diagnostics. See the table below for new equivalents of +the old macros:

    + ++++ + + + + + + + + + + + + + +

    Before

    +

    Now

    +

    BOOST_MPL_ASSERT_IS_SAME(t1, t2)

    +

    BOOST_MPL_ASSERT(( boost::is_same<t1,t2> ))

    +

    BOOST_MPL_ASSERT_IS_NOT_SAME(t1, t2)

    +

    BOOST_MPL_ASSERT_NOT(( boost::is_same<t1,t2> ))

    +
    +

    The "Macros/Asserts" section of the reference manual provides a +complete formal specification of the new macros' semantics.

    +
  8. +
  9. All configuration macros have been renamed to include the CFG prefix; in +particular, BOOST_MPL_NO_FULL_LAMBDA_SUPPORT has become +BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT.

    +
  10. +
  11. The following public headers/components have been renamed or removed as +obsolete:

    +
    +iterator_tag.hpp (renamed to iterator_tags.hpp)
    +project1st.hpp
    +project2nd.hpp
    +select1st.hpp
    +select2nd.hpp
    +
    +
  12. +
+
+ + + + + diff --git a/doc/tutorial/representing-dimensions.html b/doc/tutorial/representing-dimensions.html new file mode 100644 index 0000000..367dc0e --- /dev/null +++ b/doc/tutorial/representing-dimensions.html @@ -0,0 +1,153 @@ + + + + + + +THE BOOST MPL LIBRARY: Representing Dimensions + + + + + +
Front Page / Tutorial: Metafunctions and Higher-Order Metaprogramming / Dimensional Analysis / Representing Dimensions
+
+

Representing Dimensions

+

An international standard called Système +International d'Unites (SI), breaks every quantity down into a +combination of the dimensions mass, length (or position), +time, charge, temperature, intensity, and angle. To be +reasonably general, our system would have to be able to +represent seven or more fundamental dimensions. It also needs +the ability to represent composite dimensions that, like force, +are built through multiplication or division of the fundamental +ones.

+

In general, a composite dimension is the product of powers of +fundamental dimensions. [1] If we were going to represent +these powers for manipulation at runtime, we could use an array of +seven ints, with each position in the array holding the power +of a different fundamental dimension:

+
+typedef int dimension[7]; // m  l  t  ...
+dimension const mass      = {1, 0, 0, 0, 0, 0, 0};
+dimension const length    = {0, 1, 0, 0, 0, 0, 0};
+dimension const time      = {0, 0, 1, 0, 0, 0, 0};
+...
+
+ + + + + +
[1]Divisors just contribute negative exponents, since +1/x = x-1.
+

In that representation, force would be:

+
+dimension const force  = {1, 1, -2, 0, 0, 0, 0};
+
+ + +

that is, mlt-2. However, if we want to get dimensions into the +type system, these arrays won't do the trick: they're all +the same type! Instead, we need types that themselves represent +sequences of numbers, so that two masses have the same type and a +mass is a different type from a length.

+

Fortunately, the MPL provides us with a collection of type +sequences. For example, we can build a sequence of the built-in +signed integral types this way:

+
+#include <boost/mpl/vector.hpp>
+
+typedef boost::mpl::vector<
+     signed char, short, int, long> signed_types;
+
+

How can we use a type sequence to represent numbers? Just as +numerical metafunctions pass and return wrapper types having a +nested ::value, so numerical sequences are really sequences of +wrapper types (another example of polymorphism). To make this sort +of thing easier, MPL supplies the int_<N> class template, which +presents its integral argument as a nested ::value:

+
+#include <boost/mpl/int.hpp>
+
+namespace mpl = boost::mpl; // namespace alias
+static int const five = mpl::int_<5>::value;
+
+ + +

In fact, the library contains a whole suite of integral constant +wrappers such as long_ and bool_, each one wrapping a +different type of integral constant within a class template.

+

Now we can build our fundamental dimensions:

+
+typedef mpl::vector<
+   mpl::int_<1>, mpl::int_<0>, mpl::int_<0>, mpl::int_<0>
+ , mpl::int_<0>, mpl::int_<0>, mpl::int_<0>
+> mass;
+
+typedef mpl::vector<
+   mpl::int_<0>, mpl::int_<1>, mpl::int_<0>, mpl::int_<0>
+ , mpl::int_<0>, mpl::int_<0>, mpl::int_<0>
+> length;
+...
+
+ +

Whew! That's going to get tiring pretty quickly. Worse, it's hard +to read and verify: The essential information, the powers of each +fundamental dimension, is buried in repetitive syntactic "noise." +Accordingly, MPL supplies integral sequence wrappers that allow +us to write:

+
+#include <boost/mpl/vector_c.hpp>
+
+typedef mpl::vector_c<int,1,0,0,0,0,0,0> mass;
+typedef mpl::vector_c<int,0,1,0,0,0,0,0> length; // or position 
+typedef mpl::vector_c<int,0,0,1,0,0,0,0> time;
+typedef mpl::vector_c<int,0,0,0,1,0,0,0> charge;
+typedef mpl::vector_c<int,0,0,0,0,1,0,0> temperature;
+typedef mpl::vector_c<int,0,0,0,0,0,1,0> intensity;
+typedef mpl::vector_c<int,0,0,0,0,0,0,1> angle;
+
+

Even though they have different types, you can think of these +mpl::vector_c specializations as being equivalent to the more +verbose versions above that use mpl::vector.

+

If we want, we can also define a few composite dimensions:

+
+// base dimension:        m l  t ... 
+typedef mpl::vector_c<int,0,1,-1,0,0,0,0> velocity;     // l/t
+typedef mpl::vector_c<int,0,1,-2,0,0,0,0> acceleration; // l/(t2)
+typedef mpl::vector_c<int,1,1,-1,0,0,0,0> momentum;     // ml/t
+typedef mpl::vector_c<int,1,1,-2,0,0,0,0> force;        // ml/(t2)
+
+

And, incidentally, the dimensions of scalars (like pi) can be +described as:

+
+typedef mpl::vector_c<int,0,0,0,0,0,0,0> scalar;
+
+ +
+ + + + + diff --git a/doc/tutorial/representing-quantities.html b/doc/tutorial/representing-quantities.html new file mode 100644 index 0000000..323d2f5 --- /dev/null +++ b/doc/tutorial/representing-quantities.html @@ -0,0 +1,55 @@ + + + + + + +THE BOOST MPL LIBRARY: Representing Quantities + + + + + +
Front Page / Tutorial: Metafunctions and Higher-Order Metaprogramming / Dimensional Analysis / Representing Quantities
+
+

Representing Quantities

+

The types listed above are still pure metadata; to typecheck real +computations we'll need to somehow bind them to our runtime data. +A simple numeric value wrapper, parameterized on the number type T +and on its dimensions, fits the bill:

+
+template <class T, class Dimensions>
+struct quantity
+{
+    explicit quantity(T x)
+       : m_value(x)
+    {}
+
+    T value() const { return m_value; }
+ private:
+    T m_value;
+};
+
+ +

Now we have a way to represent numbers associated with dimensions. +For instance, we can say:

+
+quantity<float,length> l( 1.0f );
+quantity<float,mass> m( 2.0f );
+
+

Note that Dimensions doesn't appear anywhere in the definition +of quantity outside the template parameter list; its only +role is to ensure that l and m have different types. +Because they do, we cannot make the mistake of assigning a length +to a mass:

+
+m = l;    // compile-time type error
+
+ +
+ + + + + diff --git a/doc/tutorial/resources.html b/doc/tutorial/resources.html new file mode 100644 index 0000000..0242cd1 --- /dev/null +++ b/doc/tutorial/resources.html @@ -0,0 +1,49 @@ + + + + + + +THE BOOST MPL LIBRARY: Resources + + + + + +
Front Page / Resources
+
+

Resources

+"C++ Template Metaprogramming" cover

For those of you whose interest in metaprogramming is not fully +satisfied by this documentation, we've collected a few references +to other resources that we think you are likely to fancy. Most +notably, a book named "C++ Template Metaprogramming: Concepts, +Tools, and Techniques from Boost and Beyond" by David Abrahams +and Aleksey Gurtovoy is considered to be the most authoritative and +up-do-date treatment of the subject as of today. The tutorial +included with this documentation is in fact an excerpt from this +work.

+

Other notable book resources include Andrei Alexandrescu's "Modern C++ Design: Generic +Programming and Design Patterns Applied", in which +Andrei explorers the appication of C++ metaprogramming techniques to implementing +highly reusable and configurable generic designs, and "C++ Templates - The +Complete Guide", by David Vandevoorde and Nicolai M. Josuttis — the book +on the details and workings of the C++ template system.

+

We can also recommend a number online resources:

+ + +

Finally, if you come accross a high-quality, notable work on the +topic that you think should be listed here, please let us know!

+
+ + + + + diff --git a/doc/tutorial/tag-dispatching-protocol.html b/doc/tutorial/tag-dispatching-protocol.html new file mode 100644 index 0000000..7f77a85 --- /dev/null +++ b/doc/tutorial/tag-dispatching-protocol.html @@ -0,0 +1,75 @@ + + + + + + +THE BOOST MPL LIBRARY: Tag Dispatching Protocol + + + + + +
Front Page / Changelog & History / Changes in Boost 1.32.0 Release / Tag Dispatching Protocol
+
+

Tag Dispatching Protocol

+

The mechanism used to select algorithm implementations based on +sequence family has been changed to use metafunction classes:

+ ++++ + + + + + + + + + + +
BeforeNow
name_traits<Tag>::algorithm<...>::typename_impl<Tag>::apply<...>::type
+

If your code implemented a custom sequence, it needs to be adjusted +according to the above table; for example:

+ ++++ + + + + + + + + + + +
BeforeNow
+template<> struct begin_traits<my_tag>
+{
+    template< typename S > struct algorithm
+    {
+        typedef ... type;
+    };
+};
+
+
+template<> struct begin_impl<my_tag>
+{
+    template< typename S > struct apply
+    {
+        typedef ... type;
+    };
+};
+
+
+
+ + + + + diff --git a/doc/tutorial/technical-details.html b/doc/tutorial/technical-details.html new file mode 100644 index 0000000..0d11aed --- /dev/null +++ b/doc/tutorial/technical-details.html @@ -0,0 +1,28 @@ + + + + + + +THE BOOST MPL LIBRARY: Technical Details + + + + + +
Front Page / Technical Details
+
+

Technical Details

+

This section collects a few technical details on the library's organization that +do not belong into the reference manual.

+ +
+ + + + + diff --git a/doc/tutorial/the-apply-metafunction.html b/doc/tutorial/the-apply-metafunction.html new file mode 100644 index 0000000..48bb3d8 --- /dev/null +++ b/doc/tutorial/the-apply-metafunction.html @@ -0,0 +1,76 @@ + + + + + + +THE BOOST MPL LIBRARY: The apply Metafunction + + + + + +
Front Page / Tutorial: Metafunctions and Higher-Order Metaprogramming / Handling Placeholders / The apply Metafunction
+
+

The apply Metafunction

+

Invoking the result of lambda is such a common pattern +that MPL provides an apply metafunction to do just +that. Using mpl::apply, our flexible version of twice +becomes:

+
+#include <boost/mpl/apply.hpp>
+
+template <class F, class X>
+struct twice
+   : mpl::apply<F, typename mpl::apply<F,X>::type>
+{};
+
+ +

You can think of mpl::apply as being just like the apply1 +template that we wrote, with two additional features:

+
    +
  1. While apply1 operates only on metafunction classes, the first +argument to mpl::apply can be any lambda expression +(including those built with placeholders).

    +
  2. +
  3. While apply1 accepts only one additional argument to which +the metafunction class will be applied, mpl::apply can +invoke its first argument on any number from zero to five +additional arguments. [5] For example:

    +
    +// binary lambda expression applied to 2 additional arguments
    +mpl::apply<
    +    mpl::plus<_1,_2>   
    +  , mpl::int_<6>
    +  , mpl::int_<7>
    +>::type::value // == 13
    +
    +
  4. +
+ + + + + +
[5]See the Configuration Macros section of the the MPL reference manual +for a description of how to change the maximum number of +arguments handled by mpl::apply.
+ +
+

Guideline

+

When writing a metafunction that invokes one of its arguments, +use mpl::apply so that it works with lambda expressions.

+
+
+ + + + + diff --git a/doc/tutorial/the-importance-of-being.html b/doc/tutorial/the-importance-of-being.html new file mode 100644 index 0000000..b2e7dd3 --- /dev/null +++ b/doc/tutorial/the-importance-of-being.html @@ -0,0 +1,55 @@ + + + + + + +THE BOOST MPL LIBRARY: The Importance of Being Lazy + + + + + +
Front Page / Tutorial: Metafunctions and Higher-Order Metaprogramming / Lambda Details / The Importance of Being Lazy
+
+

The Importance of Being Lazy

+

Recall the definition of always_int from the previous chapter:

+
+struct always_int
+{
+    typedef int type;
+};
+
+

Nullary metafunctions might not seem very important at first, since +something like add_pointer<int> could be replaced by int* in +any lambda expression where it appears. Not all nullary +metafunctions are that simple, though:

+
+typedef mpl::vector<int, char*, double&> seq;
+typedef mpl::transform<seq, boost::add_pointer<_> > calc_ptr_seq;
+
+ +

Note that calc_ptr_seq is a nullary metafunction, since it has +transform's nested ::type. A C++ template is not +instantiated until we actually "look inside it," though. Just +naming calc_ptr_seq does not cause it to be evaluated, since we +haven't accessed its ::type yet.

+

Metafunctions can be invoked lazily, rather than immediately upon +supplying all of their arguments. We can use lazy evaluation to +improve compilation time when a metafunction result is only going +to be used conditionally. We can sometimes also avoid contorting +program structure by naming an invalid computation without +actually performing it. That's what we've done with +calc_ptr_seq above, since you can't legally form double&*. +Laziness and all of its virtues will be a recurring theme +throughout this book.

+
+ + + + + diff --git a/doc/tutorial/the-lambda-metafunction.html b/doc/tutorial/the-lambda-metafunction.html new file mode 100644 index 0000000..191f587 --- /dev/null +++ b/doc/tutorial/the-lambda-metafunction.html @@ -0,0 +1,85 @@ + + + + + + +THE BOOST MPL LIBRARY: The lambda Metafunction + + + + + +
Front Page / Tutorial: Metafunctions and Higher-Order Metaprogramming / Handling Placeholders / The lambda Metafunction
+
+

The lambda Metafunction

+

We can generate a metafunction class from +boost::add_pointer<_1>, using MPL's lambda metafunction:

+
+template <class X>
+struct two_pointers
+  : twice<typename mpl::lambda<boost::add_pointer<_1> >::type, X>
+{};
+
+BOOST_STATIC_ASSERT((
+    boost::is_same<
+        two_pointers<int>::type
+      , int**
+    >::value
+));
+
+ +

We'll refer to metafunction classes like add_pointer_f and +placeholder expressions like boost::add_pointer<_1> +as lambda expressions. The term, meaning "unnamed function +object," was introduced in the 1930s by the logician Alonzo Church +as part of a fundamental theory of computation he called the +lambda-calculus. [4] MPL uses the somewhat obscure word +lambda because of its well-established precedent in functional +programming languages.

+ + + + + +
[4]See http://en.wikipedia.org/wiki/Lambda_calculus for +an in-depth treatment, including a reference to Church's paper +proving that the equivalence of lambda expressions is in general +not decidable.
+

Although its primary purpose is to turn placeholder expressions +into metafunction classes, mpl::lambda can accept any lambda +expression, even if it's already a metafunction class. In that +case, lambda returns its argument unchanged. MPL algorithms +like transform call lambda internally, before invoking the +resulting metafunction class, so that they work equally well with +either kind of lambda expression. We can apply the same strategy +to twice:

+
+template <class F, class X>
+struct twice
+   : apply1<
+         typename mpl::lambda<F>::type
+       , typename apply1<
+             typename mpl::lambda<F>::type
+           , X
+         >::type
+     >
+{};
+
+

Now we can use twice with metafunction classes and +placeholder expressions:

+
+int* x;
+
+twice<add_pointer_f, int>::type           p = &x;
+twice<boost::add_pointer<_1>, int>::type q = &x;
+
+ +
+ + + + + diff --git a/doc/tutorial/tutorial-metafunctions.html b/doc/tutorial/tutorial-metafunctions.html new file mode 100644 index 0000000..b146835 --- /dev/null +++ b/doc/tutorial/tutorial-metafunctions.html @@ -0,0 +1,47 @@ + + + + + + +THE BOOST MPL LIBRARY: Tutorial: Metafunctions and Higher-Order Metaprogramming + + + + + +
Front Page / Tutorial: Metafunctions and Higher-Order Metaprogramming
+
+

Tutorial: Metafunctions and Higher-Order Metaprogramming

+ +++ + + + +
Note:The following material is an excerpt from Chapter 3 of "C++ Template Metaprogramming", +by David Abrahams and Aleksey Gurtovoy, ISBN 0321227255, http://www.awprofessional.com/titles/0321227255. +Copyright (c) 2005 by Pearson Education, Inc. Reprinted with permission.
+

With the foundation laid so far, we're ready to explore one of the +most basic uses for template metaprogramming techniques: adding +static type checking to traditionally unchecked operations. We'll +look at a practical example from science and engineering that can +find applications in almost any numerical code. +Along the way you'll learn some important new concepts and +get a taste of metaprogramming at a high level using the MPL.

+ +
+ + + + + diff --git a/doc/tutorial/tutorial_toc.html b/doc/tutorial/tutorial_toc.html new file mode 100644 index 0000000..c71ee96 --- /dev/null +++ b/doc/tutorial/tutorial_toc.html @@ -0,0 +1,77 @@ + + + + + + +THE BOOST MPL LIBRARY: Full TOC + + + + +
+

Table of Contents

+ + + + + +